From e7549b926dd3ceec048f5689df90d4ec970c9419 Mon Sep 17 00:00:00 2001 From: Wolfgang Wiedmeyer Date: Fri, 23 Oct 2015 13:30:20 +0200 Subject: more driver stuff from 3.2.72 --- drivers/idle/intel_idle.c | 178 +- drivers/ieee802154/Makefile | 2 - drivers/ieee802154/fakehard.c | 2 - drivers/infiniband/core/addr.c | 1 + drivers/infiniband/core/cache.c | 3 +- drivers/infiniband/core/cm.c | 64 +- drivers/infiniband/core/cm_msgs.h | 32 +- drivers/infiniband/core/cma.c | 158 +- drivers/infiniband/core/device.c | 6 + drivers/infiniband/core/fmr_pool.c | 1 + drivers/infiniband/core/iwcm.c | 35 + drivers/infiniband/core/mad.c | 4 + drivers/infiniband/core/multicast.c | 1 + drivers/infiniband/core/netlink.c | 1 + drivers/infiniband/core/packer.c | 1 + drivers/infiniband/core/sysfs.c | 27 +- drivers/infiniband/core/ucm.c | 2 +- drivers/infiniband/core/ucma.c | 8 +- drivers/infiniband/core/ud_header.c | 1 + drivers/infiniband/core/umem.c | 20 +- drivers/infiniband/core/user_mad.c | 54 +- drivers/infiniband/core/uverbs.h | 21 +- drivers/infiniband/core/uverbs_cmd.c | 735 ++- drivers/infiniband/core/uverbs_main.c | 74 +- drivers/infiniband/core/uverbs_marshall.c | 1 + drivers/infiniband/core/verbs.c | 377 +- drivers/infiniband/hw/amso1100/c2.c | 12 +- drivers/infiniband/hw/amso1100/c2_ae.c | 5 + drivers/infiniband/hw/amso1100/c2_intr.c | 5 + drivers/infiniband/hw/amso1100/c2_provider.c | 14 +- drivers/infiniband/hw/cxgb3/Makefile | 2 +- drivers/infiniband/hw/cxgb3/iwch_cm.c | 10 + drivers/infiniband/hw/cxgb3/iwch_ev.c | 6 + drivers/infiniband/hw/cxgb3/iwch_provider.c | 9 +- drivers/infiniband/hw/cxgb3/iwch_provider.h | 1 + drivers/infiniband/hw/cxgb3/iwch_qp.c | 14 +- drivers/infiniband/hw/cxgb4/Makefile | 2 +- drivers/infiniband/hw/cxgb4/cm.c | 468 +- drivers/infiniband/hw/cxgb4/cq.c | 8 +- drivers/infiniband/hw/cxgb4/device.c | 41 +- drivers/infiniband/hw/cxgb4/ev.c | 10 +- drivers/infiniband/hw/cxgb4/iw_cxgb4.h | 23 +- drivers/infiniband/hw/cxgb4/mem.c | 2 +- drivers/infiniband/hw/cxgb4/provider.c | 8 - drivers/infiniband/hw/cxgb4/qp.c | 42 +- drivers/infiniband/hw/cxgb4/resource.c | 9 +- drivers/infiniband/hw/cxgb4/user.h | 1 + drivers/infiniband/hw/ehca/ehca_cq.c | 1 + drivers/infiniband/hw/ehca/ehca_eq.c | 4 +- drivers/infiniband/hw/ehca/ehca_qp.c | 3 + drivers/infiniband/hw/ehca/ehca_tools.h | 2 +- drivers/infiniband/hw/ipath/ipath_diag.c | 69 +- drivers/infiniband/hw/ipath/ipath_driver.c | 1 + drivers/infiniband/hw/ipath/ipath_file_ops.c | 12 +- drivers/infiniband/hw/ipath/ipath_init_chip.c | 2 + drivers/infiniband/hw/ipath/ipath_mad.c | 198 +- drivers/infiniband/hw/ipath/ipath_srq.c | 5 + drivers/infiniband/hw/ipath/ipath_sysfs.c | 1 + drivers/infiniband/hw/ipath/ipath_user_pages.c | 6 +- drivers/infiniband/hw/ipath/ipath_user_sdma.c | 7 +- drivers/infiniband/hw/ipath/ipath_verbs.c | 1 + drivers/infiniband/hw/mlx4/Kconfig | 3 +- drivers/infiniband/hw/mlx4/ah.c | 6 +- drivers/infiniband/hw/mlx4/mad.c | 80 +- drivers/infiniband/hw/mlx4/main.c | 129 +- drivers/infiniband/hw/mlx4/mlx4_ib.h | 14 + drivers/infiniband/hw/mlx4/qp.c | 146 +- drivers/infiniband/hw/mlx4/srq.c | 10 +- drivers/infiniband/hw/mthca/mthca_catas.c | 1 + drivers/infiniband/hw/mthca/mthca_cmd.c | 277 +- drivers/infiniband/hw/mthca/mthca_cmd.h | 93 +- drivers/infiniband/hw/mthca/mthca_cq.c | 15 +- drivers/infiniband/hw/mthca/mthca_eq.c | 43 +- drivers/infiniband/hw/mthca/mthca_mad.c | 15 +- drivers/infiniband/hw/mthca/mthca_main.c | 175 +- drivers/infiniband/hw/mthca/mthca_mcg.c | 101 +- drivers/infiniband/hw/mthca/mthca_memfree.c | 43 +- drivers/infiniband/hw/mthca/mthca_mr.c | 37 +- drivers/infiniband/hw/mthca/mthca_provider.c | 83 +- drivers/infiniband/hw/mthca/mthca_qp.c | 49 +- drivers/infiniband/hw/mthca/mthca_reset.c | 2 +- drivers/infiniband/hw/mthca/mthca_srq.c | 33 +- drivers/infiniband/hw/nes/Makefile | 2 +- drivers/infiniband/hw/nes/nes.c | 8 +- drivers/infiniband/hw/nes/nes.h | 17 +- drivers/infiniband/hw/nes/nes_cm.c | 1123 ++-- drivers/infiniband/hw/nes/nes_cm.h | 75 +- drivers/infiniband/hw/nes/nes_hw.c | 118 +- drivers/infiniband/hw/nes/nes_hw.h | 39 +- drivers/infiniband/hw/nes/nes_nic.c | 83 +- drivers/infiniband/hw/nes/nes_utils.c | 53 +- drivers/infiniband/hw/nes/nes_verbs.c | 21 +- drivers/infiniband/hw/nes/nes_verbs.h | 12 +- drivers/infiniband/hw/qib/qib.h | 31 +- drivers/infiniband/hw/qib/qib_diag.c | 1 + drivers/infiniband/hw/qib/qib_driver.c | 21 +- drivers/infiniband/hw/qib/qib_eeprom.c | 180 - drivers/infiniband/hw/qib/qib_file_ops.c | 19 +- drivers/infiniband/hw/qib/qib_iba6120.c | 4 +- drivers/infiniband/hw/qib/qib_iba7220.c | 31 +- drivers/infiniband/hw/qib/qib_iba7322.c | 225 +- drivers/infiniband/hw/qib/qib_init.c | 10 +- drivers/infiniband/hw/qib/qib_keys.c | 4 + drivers/infiniband/hw/qib/qib_mad.c | 80 +- drivers/infiniband/hw/qib/qib_mad.h | 143 +- drivers/infiniband/hw/qib/qib_pcie.c | 9 +- drivers/infiniband/hw/qib/qib_qp.c | 90 +- drivers/infiniband/hw/qib/qib_qsfp.c | 35 +- drivers/infiniband/hw/qib/qib_qsfp.h | 3 + drivers/infiniband/hw/qib/qib_rc.c | 46 +- drivers/infiniband/hw/qib/qib_ruc.c | 7 +- drivers/infiniband/hw/qib/qib_sd7220.c | 1 + drivers/infiniband/hw/qib/qib_sdma.c | 1 + drivers/infiniband/hw/qib/qib_srq.c | 5 + drivers/infiniband/hw/qib/qib_sysfs.c | 37 +- drivers/infiniband/hw/qib/qib_tx.c | 1 + drivers/infiniband/hw/qib/qib_uc.c | 25 +- drivers/infiniband/hw/qib/qib_ud.c | 9 +- drivers/infiniband/hw/qib/qib_user_pages.c | 4 +- drivers/infiniband/hw/qib/qib_user_sdma.c | 6 +- drivers/infiniband/hw/qib/qib_verbs.c | 51 +- drivers/infiniband/hw/qib/qib_verbs.h | 7 +- drivers/infiniband/ulp/ipoib/ipoib.h | 2 +- drivers/infiniband/ulp/ipoib/ipoib_cm.c | 13 +- drivers/infiniband/ulp/ipoib/ipoib_fs.c | 8 +- drivers/infiniband/ulp/ipoib/ipoib_ib.c | 37 +- drivers/infiniband/ulp/ipoib/ipoib_main.c | 4 +- drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 8 +- drivers/infiniband/ulp/iser/iscsi_iser.c | 102 +- drivers/infiniband/ulp/iser/iscsi_iser.h | 7 +- drivers/infiniband/ulp/iser/iser_initiator.c | 35 +- drivers/infiniband/ulp/iser/iser_verbs.c | 33 +- drivers/infiniband/ulp/srp/ib_srp.c | 8 +- drivers/input/gameport/gameport.c | 2 +- drivers/input/joystick/analog.c | 4 +- drivers/input/joystick/as5011.c | 1 + drivers/input/joystick/xpad.c | 52 +- drivers/input/mouse/alps.c | 63 +- drivers/input/mouse/bcm5974.c | 80 + drivers/input/mouse/elantech.c | 817 ++- drivers/input/mouse/elantech.h | 59 +- drivers/input/mouse/gpio_mouse.c | 2 +- drivers/input/mouse/hgpk.c | 85 +- drivers/input/mouse/hgpk.h | 11 - drivers/input/mouse/lifebook.c | 10 +- drivers/input/mouse/logips2pp.c | 16 +- drivers/input/mouse/psmouse-base.c | 67 +- drivers/input/mouse/psmouse.h | 25 + drivers/input/mouse/pxa930_trkball.c | 3 +- drivers/input/mouse/sentelic.c | 22 +- drivers/input/mouse/sentelic.h | 3 +- drivers/input/mouse/synaptics.c | 925 ++- drivers/input/mouse/synaptics.h | 52 +- drivers/input/mouse/synaptics_i2c.c | 4 +- drivers/input/serio/ams_delta_serio.c | 1 + drivers/input/serio/at32psif.c | 2 +- drivers/input/serio/hp_sdc.c | 2 +- drivers/input/serio/i8042-x86ia64io.h | 98 + drivers/input/serio/i8042.c | 37 +- drivers/input/serio/libps2.c | 2 +- drivers/input/serio/sa1111ps2.c | 6 +- drivers/input/serio/serio_raw.c | 215 +- drivers/input/serio/serport.c | 45 +- drivers/input/serio/xilinx_ps2.c | 2 +- drivers/input/tablet/aiptek.c | 1 - drivers/input/tablet/wacom.h | 10 +- drivers/input/tablet/wacom_sys.c | 383 +- drivers/input/tablet/wacom_wac.c | 167 +- drivers/isdn/Kconfig | 2 +- drivers/isdn/capi/kcapi_proc.c | 1 + drivers/isdn/divert/divert_procfs.c | 6 + drivers/isdn/gigaset/asyncdata.c | 1 + drivers/isdn/gigaset/capi.c | 5 + drivers/isdn/gigaset/dummyll.c | 1 + drivers/isdn/gigaset/ev-layer.c | 5 +- drivers/isdn/gigaset/gigaset.h | 2 +- drivers/isdn/gigaset/i4l.c | 1 + drivers/isdn/gigaset/interface.c | 1 + drivers/isdn/hardware/mISDN/avmfritz.c | 1 + drivers/isdn/hardware/mISDN/hfcmulti.c | 1 + drivers/isdn/hardware/mISDN/hfcpci.c | 1 + drivers/isdn/hardware/mISDN/mISDNinfineon.c | 1 + drivers/isdn/hardware/mISDN/mISDNipac.c | 1 + drivers/isdn/hardware/mISDN/mISDNisar.c | 1 + drivers/isdn/hardware/mISDN/netjet.c | 1 + drivers/isdn/hardware/mISDN/speedfax.c | 1 + drivers/isdn/hardware/mISDN/w6692.c | 1 + drivers/isdn/hisax/callc.c | 4 +- drivers/isdn/hisax/hisax.h | 5 +- drivers/isdn/hisax/hisax_fcpcipnp.c | 1 + drivers/isdn/hisax/isdnl1.h | 2 +- drivers/isdn/hisax/isdnl3.c | 2 +- drivers/isdn/hisax/l3dss1.c | 6 +- drivers/isdn/hisax/st5481_d.c | 4 +- drivers/isdn/i4l/isdn_bsdcomp.c | 2 +- drivers/isdn/i4l/isdn_common.c | 4 +- drivers/isdn/i4l/isdn_net.c | 8 +- drivers/isdn/i4l/isdn_tty.c | 3 +- drivers/isdn/isdnloop/isdnloop.c | 31 +- drivers/isdn/mISDN/clock.c | 1 + drivers/isdn/mISDN/dsp_audio.c | 1 + drivers/isdn/mISDN/dsp_core.c | 3 +- drivers/isdn/mISDN/dsp_pipeline.c | 1 + drivers/isdn/mISDN/l1oip_codec.c | 6 +- drivers/isdn/mISDN/socket.c | 14 +- drivers/lguest/core.c | 20 +- drivers/lguest/interrupts_and_traps.c | 10 +- drivers/lguest/lg.h | 2 + drivers/lguest/lguest_device.c | 38 +- drivers/lguest/lguest_user.c | 18 +- drivers/lguest/page_tables.c | 282 +- drivers/lguest/x86/core.c | 107 +- drivers/macintosh/nvram.c | 4 + drivers/macintosh/via-macii.c | 2 +- drivers/macintosh/via-maciisi.c | 4 +- drivers/macintosh/windfarm_core.c | 2 +- drivers/media/common/saa7146_core.c | 75 +- drivers/media/common/saa7146_fops.c | 119 +- drivers/media/common/saa7146_hlp.c | 15 +- drivers/media/common/saa7146_i2c.c | 60 +- drivers/media/common/saa7146_vbi.c | 48 +- drivers/media/common/saa7146_video.c | 184 +- drivers/media/common/tuners/Kconfig | 10 + drivers/media/common/tuners/Makefile | 5 +- drivers/media/common/tuners/mt20xx.c | 24 +- drivers/media/common/tuners/mxl5005s.c | 22 +- drivers/media/common/tuners/mxl5007t.c | 3 +- drivers/media/common/tuners/tda18212.c | 31 +- drivers/media/common/tuners/tda18212_priv.h | 44 - drivers/media/common/tuners/tda18218.c | 2 +- drivers/media/common/tuners/tda18271-common.c | 32 +- drivers/media/common/tuners/tda18271-fe.c | 2 +- drivers/media/common/tuners/tda18271-priv.h | 39 +- drivers/media/common/tuners/tda827x.c | 8 +- drivers/media/common/tuners/tuner-types.c | 5 + drivers/media/common/tuners/tuner-xc2028.c | 18 +- drivers/media/common/tuners/tuner-xc2028.h | 1 + drivers/media/dvb/Kconfig | 4 + drivers/media/dvb/Makefile | 3 +- drivers/media/dvb/b2c2/Makefile | 4 +- drivers/media/dvb/b2c2/flexcop-common.h | 1 + drivers/media/dvb/bt8xx/Makefile | 8 +- drivers/media/dvb/bt8xx/dvb-bt8xx.c | 4 +- drivers/media/dvb/dm1105/Makefile | 2 +- drivers/media/dvb/dm1105/dm1105.c | 1 + drivers/media/dvb/dvb-core/Makefile | 4 +- drivers/media/dvb/dvb-core/dmxdev.c | 8 +- drivers/media/dvb/dvb-core/dvb_frontend.c | 98 +- drivers/media/dvb/dvb-core/dvb_frontend.h | 1 + drivers/media/dvb/dvb-core/dvb_net.c | 2 +- drivers/media/dvb/dvb-core/dvb_net.h | 21 +- drivers/media/dvb/dvb-usb/Kconfig | 29 + drivers/media/dvb/dvb-usb/Makefile | 16 +- drivers/media/dvb/dvb-usb/a800.c | 4 +- drivers/media/dvb/dvb-usb/af9005-fe.c | 2 - drivers/media/dvb/dvb-usb/af9005-remote.c | 2 +- drivers/media/dvb/dvb-usb/af9005.c | 10 +- drivers/media/dvb/dvb-usb/af9015.c | 183 +- drivers/media/dvb/dvb-usb/af9015.h | 1 - drivers/media/dvb/dvb-usb/anysee.c | 406 +- drivers/media/dvb/dvb-usb/anysee.h | 17 +- drivers/media/dvb/dvb-usb/au6610.c | 9 +- drivers/media/dvb/dvb-usb/az6027.c | 26 +- drivers/media/dvb/dvb-usb/ce6230.c | 9 +- drivers/media/dvb/dvb-usb/cinergyT2-core.c | 5 +- drivers/media/dvb/dvb-usb/cxusb.c | 142 +- drivers/media/dvb/dvb-usb/dib0700_core.c | 36 +- drivers/media/dvb/dvb-usb/dib0700_devices.c | 549 +- drivers/media/dvb/dvb-usb/dibusb-common.c | 27 +- drivers/media/dvb/dvb-usb/dibusb-mb.c | 31 +- drivers/media/dvb/dvb-usb/dibusb-mc.c | 3 + drivers/media/dvb/dvb-usb/digitv.c | 16 +- drivers/media/dvb/dvb-usb/dtt200u.c | 14 +- drivers/media/dvb/dvb-usb/dtv5100.c | 11 +- drivers/media/dvb/dvb-usb/dvb-usb-dvb.c | 153 +- drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 9 + drivers/media/dvb/dvb-usb/dvb-usb-init.c | 41 +- drivers/media/dvb/dvb-usb/dvb-usb-urb.c | 28 +- drivers/media/dvb/dvb-usb/dvb-usb.h | 39 +- drivers/media/dvb/dvb-usb/dw2102.c | 115 +- drivers/media/dvb/dvb-usb/ec168.c | 9 +- drivers/media/dvb/dvb-usb/friio.c | 7 +- drivers/media/dvb/dvb-usb/gl861.c | 9 +- drivers/media/dvb/dvb-usb/gp8psk-fe.c | 17 +- drivers/media/dvb/dvb-usb/gp8psk.c | 5 +- drivers/media/dvb/dvb-usb/gp8psk.h | 3 - drivers/media/dvb/dvb-usb/lmedm04.c | 68 +- drivers/media/dvb/dvb-usb/m920x.c | 58 +- drivers/media/dvb/dvb-usb/nova-t-usb2.c | 4 +- drivers/media/dvb/dvb-usb/opera1.c | 13 +- drivers/media/dvb/dvb-usb/technisat-usb2.c | 32 +- drivers/media/dvb/dvb-usb/ttusb2.c | 407 +- drivers/media/dvb/dvb-usb/umt-010.c | 8 +- drivers/media/dvb/dvb-usb/usb-urb.c | 4 +- drivers/media/dvb/dvb-usb/vp702x.c | 5 +- drivers/media/dvb/dvb-usb/vp7045.c | 5 +- drivers/media/dvb/dvb-usb/vp7045.h | 3 - drivers/media/dvb/firewire/firedtv-avc.c | 2 +- drivers/media/dvb/firewire/firedtv-ci.c | 34 +- drivers/media/dvb/frontends/Kconfig | 51 + drivers/media/dvb/frontends/Makefile | 11 +- drivers/media/dvb/frontends/au8522_decoder.c | 2 +- drivers/media/dvb/frontends/cx24113.c | 20 +- drivers/media/dvb/frontends/cx24116.c | 14 +- drivers/media/dvb/frontends/cxd2820r.h | 13 +- drivers/media/dvb/frontends/cxd2820r_c.c | 1 - drivers/media/dvb/frontends/cxd2820r_core.c | 74 +- drivers/media/dvb/frontends/cxd2820r_priv.h | 5 +- drivers/media/dvb/frontends/cxd2820r_t.c | 1 - drivers/media/dvb/frontends/cxd2820r_t2.c | 1 - drivers/media/dvb/frontends/dib3000.h | 2 +- drivers/media/dvb/frontends/dib3000mb.c | 2 +- drivers/media/dvb/frontends/dib7000p.c | 7 +- drivers/media/dvb/frontends/dib8000.c | 33 +- drivers/media/dvb/frontends/dib9000.c | 3 +- drivers/media/dvb/frontends/dibx000_common.c | 1 + drivers/media/dvb/frontends/drxd_hard.c | 33 +- drivers/media/dvb/frontends/ds3000.c | 7 + drivers/media/dvb/frontends/itd1000.c | 25 +- drivers/media/dvb/frontends/nxt6000.c | 2 +- drivers/media/dvb/frontends/s5h1420.c | 14 +- drivers/media/dvb/frontends/stb0899_algo.c | 3 + drivers/media/dvb/frontends/stb0899_drv.c | 6 +- drivers/media/dvb/frontends/stv0288.c | 29 +- drivers/media/dvb/frontends/stv090x.c | 35 +- drivers/media/dvb/frontends/tda10048.c | 37 +- drivers/media/dvb/frontends/tda10048.h | 8 + drivers/media/dvb/mantis/Makefile | 2 +- drivers/media/dvb/mantis/hopper_cards.c | 6 +- drivers/media/dvb/mantis/mantis_ca.c | 1 + drivers/media/dvb/mantis/mantis_cards.c | 6 +- drivers/media/dvb/mantis/mantis_common.h | 6 +- drivers/media/dvb/mantis/mantis_dma.c | 92 +- drivers/media/dvb/mantis/mantis_evm.c | 1 + drivers/media/dvb/mantis/mantis_hif.c | 1 + drivers/media/dvb/mantis/mantis_ioc.c | 1 + drivers/media/dvb/mantis/mantis_pcmcia.c | 1 + drivers/media/dvb/mantis/mantis_uart.c | 1 + drivers/media/dvb/mantis/mantis_vp1034.c | 1 + drivers/media/dvb/mantis/mantis_vp1041.c | 1 - drivers/media/dvb/ngene/Kconfig | 2 + drivers/media/dvb/ngene/Makefile | 8 +- drivers/media/dvb/ngene/ngene-cards.c | 182 +- drivers/media/dvb/ngene/ngene-core.c | 26 +- drivers/media/dvb/ngene/ngene-dvb.c | 46 +- drivers/media/dvb/ngene/ngene.h | 7 +- drivers/media/dvb/pluto2/Makefile | 2 +- drivers/media/dvb/pluto2/pluto2.c | 1 + drivers/media/dvb/pt1/Makefile | 2 +- drivers/media/dvb/siano/Makefile | 4 +- drivers/media/dvb/siano/sms-cards.c | 1 + drivers/media/dvb/siano/smscoreapi.c | 2 +- drivers/media/dvb/siano/smscoreapi.h | 1 - drivers/media/dvb/siano/smsendian.c | 1 + drivers/media/dvb/siano/smssdio.c | 1 + drivers/media/dvb/siano/smsusb.c | 1 + drivers/media/dvb/ttpci/Makefile | 4 +- drivers/media/dvb/ttpci/av7110_v4l.c | 32 +- drivers/media/dvb/ttpci/budget-av.c | 47 +- drivers/media/dvb/ttpci/budget-ci.c | 1 - drivers/media/dvb/ttpci/budget-core.c | 2 + drivers/media/dvb/ttpci/budget.h | 1 + drivers/media/dvb/ttpci/ttpci-eeprom.c | 29 + drivers/media/dvb/ttpci/ttpci-eeprom.h | 1 + drivers/media/dvb/ttusb-budget/Makefile | 2 +- drivers/media/dvb/ttusb-dec/Makefile | 2 +- drivers/media/dvb/ttusb-dec/ttusbdecfe.c | 3 + drivers/media/radio/wl128x/fmdrv.h | 5 +- drivers/media/radio/wl128x/fmdrv_v4l2.c | 13 +- drivers/media/video/au0828/Makefile | 8 +- drivers/media/video/au0828/au0828-cards.c | 12 + drivers/media/video/au0828/au0828-core.c | 1 + drivers/media/video/au0828/au0828-video.c | 5 - drivers/media/video/bt8xx/Makefile | 6 +- drivers/media/video/bt8xx/bttv-cards.c | 249 +- drivers/media/video/bt8xx/bttv-driver.c | 304 +- drivers/media/video/bt8xx/bttv-gpio.c | 4 +- drivers/media/video/bt8xx/bttv-i2c.c | 56 +- drivers/media/video/bt8xx/bttv-input.c | 37 +- drivers/media/video/bt8xx/bttv-risc.c | 25 +- drivers/media/video/bt8xx/bttv-vbi.c | 9 +- drivers/media/video/bt8xx/bttvp.h | 21 +- drivers/media/video/cpia2/cpia2.h | 5 - drivers/media/video/cpia2/cpia2_usb.c | 1 + drivers/media/video/cpia2/cpia2_v4l.c | 12 +- drivers/media/video/cx18/Makefile | 6 +- drivers/media/video/cx18/cx18-alsa-main.c | 1 + drivers/media/video/cx18/cx18-driver.c | 2 + drivers/media/video/cx18/cx18-driver.h | 6 +- drivers/media/video/cx18/cx18-fileops.c | 2 - drivers/media/video/cx18/cx18-ioctl.c | 19 +- drivers/media/video/cx18/cx18-mailbox.c | 2 +- drivers/media/video/cx18/cx18-mailbox.h | 2 +- drivers/media/video/cx18/cx18-streams.c | 13 + drivers/media/video/cx18/cx18-version.h | 8 +- drivers/media/video/cx231xx/Makefile | 10 +- drivers/media/video/cx231xx/cx231xx-avcore.c | 4 + drivers/media/video/cx231xx/cx231xx-cards.c | 78 + drivers/media/video/cx231xx/cx231xx-core.c | 4 + drivers/media/video/cx231xx/cx231xx-video.c | 29 +- drivers/media/video/cx231xx/cx231xx.h | 5 +- drivers/media/video/cx23885/Kconfig | 2 +- drivers/media/video/cx23885/Makefile | 12 +- drivers/media/video/cx23885/altera-ci.c | 1 - drivers/media/video/cx23885/cx23885-417.c | 1 - drivers/media/video/cx23885/cx23885-cards.c | 125 +- drivers/media/video/cx23885/cx23885-core.c | 112 +- drivers/media/video/cx23885/cx23885-dvb.c | 28 +- drivers/media/video/cx23885/cx23885-i2c.c | 1 + drivers/media/video/cx23885/cx23885-input.c | 6 + drivers/media/video/cx23885/cx23885-reg.h | 3 + drivers/media/video/cx23885/cx23885-vbi.c | 72 +- drivers/media/video/cx23885/cx23885-video.c | 359 +- drivers/media/video/cx23885/cx23885.h | 60 +- drivers/media/video/cx23885/cx23888-ir.c | 12 +- drivers/media/video/cx25840/Makefile | 2 +- drivers/media/video/cx25840/cx25840-audio.c | 10 +- drivers/media/video/cx25840/cx25840-core.c | 19 + drivers/media/video/cx25840/cx25840-ir.c | 13 +- drivers/media/video/cx88/Makefile | 8 +- drivers/media/video/cx88/cx88-alsa.c | 19 +- drivers/media/video/cx88/cx88-blackbird.c | 20 +- drivers/media/video/cx88/cx88-cards.c | 166 +- drivers/media/video/cx88/cx88-core.c | 8 +- drivers/media/video/cx88/cx88-dvb.c | 77 +- drivers/media/video/cx88/cx88-input.c | 4 + drivers/media/video/cx88/cx88-mpeg.c | 35 +- drivers/media/video/cx88/cx88-video.c | 65 +- drivers/media/video/cx88/cx88.h | 7 +- drivers/media/video/davinci/Kconfig | 23 + drivers/media/video/davinci/Makefile | 2 + drivers/media/video/davinci/dm355_ccdc.c | 1 + drivers/media/video/davinci/dm644x_ccdc.c | 1 + drivers/media/video/davinci/vpif.c | 2 +- drivers/media/video/davinci/vpif_capture.c | 9 +- drivers/media/video/davinci/vpif_capture.h | 7 +- drivers/media/video/davinci/vpif_display.c | 9 +- drivers/media/video/davinci/vpif_display.h | 8 +- drivers/media/video/em28xx/Kconfig | 14 +- drivers/media/video/em28xx/Makefile | 14 +- drivers/media/video/em28xx/em28xx-audio.c | 251 +- drivers/media/video/em28xx/em28xx-cards.c | 308 +- drivers/media/video/em28xx/em28xx-core.c | 129 +- drivers/media/video/em28xx/em28xx-dvb.c | 243 +- drivers/media/video/em28xx/em28xx-i2c.c | 17 +- drivers/media/video/em28xx/em28xx-input.c | 7 +- drivers/media/video/em28xx/em28xx-reg.h | 1 + drivers/media/video/em28xx/em28xx-video.c | 72 +- drivers/media/video/em28xx/em28xx.h | 27 +- drivers/media/video/et61x251/et61x251.h | 67 +- drivers/media/video/et61x251/et61x251_core.c | 18 +- drivers/media/video/et61x251/et61x251_tas5130d1b.c | 2 + drivers/media/video/gspca/Kconfig | 20 + drivers/media/video/gspca/Makefile | 4 + drivers/media/video/gspca/benq.c | 31 +- drivers/media/video/gspca/conex.c | 6 +- drivers/media/video/gspca/cpia1.c | 7 +- drivers/media/video/gspca/etoms.c | 6 +- drivers/media/video/gspca/finepix.c | 8 +- drivers/media/video/gspca/gl860/Makefile | 2 +- drivers/media/video/gspca/gl860/gl860.c | 8 +- drivers/media/video/gspca/gl860/gl860.h | 1 - drivers/media/video/gspca/gspca.c | 306 +- drivers/media/video/gspca/gspca.h | 22 +- drivers/media/video/gspca/jeilinj.c | 20 +- drivers/media/video/gspca/kinect.c | 42 +- drivers/media/video/gspca/konica.c | 16 +- drivers/media/video/gspca/m5602/Makefile | 2 +- drivers/media/video/gspca/m5602/m5602_core.c | 9 +- drivers/media/video/gspca/m5602/m5602_mt9m111.c | 28 +- drivers/media/video/gspca/m5602/m5602_ov7660.c | 21 +- drivers/media/video/gspca/m5602/m5602_ov9650.c | 19 +- drivers/media/video/gspca/m5602/m5602_po1030.c | 21 +- drivers/media/video/gspca/m5602/m5602_s5k4aa.c | 35 +- drivers/media/video/gspca/m5602/m5602_s5k83a.c | 30 +- drivers/media/video/gspca/mars.c | 6 +- drivers/media/video/gspca/mr97310a.c | 24 +- drivers/media/video/gspca/nw80x.c | 9 +- drivers/media/video/gspca/ov519.c | 172 +- drivers/media/video/gspca/ov534.c | 12 +- drivers/media/video/gspca/ov534_9.c | 516 +- drivers/media/video/gspca/pac207.c | 14 +- drivers/media/video/gspca/pac7302.c | 18 +- drivers/media/video/gspca/pac7311.c | 15 +- drivers/media/video/gspca/sn9c2028.c | 14 +- drivers/media/video/gspca/sn9c20x.c | 77 +- drivers/media/video/gspca/sonixj.c | 51 +- drivers/media/video/gspca/spca1528.c | 34 +- drivers/media/video/gspca/spca500.c | 6 +- drivers/media/video/gspca/spca501.c | 4 +- drivers/media/video/gspca/spca505.c | 8 +- drivers/media/video/gspca/spca508.c | 6 +- drivers/media/video/gspca/spca561.c | 4 +- drivers/media/video/gspca/sq905.c | 17 +- drivers/media/video/gspca/sq905c.c | 10 +- drivers/media/video/gspca/sq930x.c | 21 +- drivers/media/video/gspca/stk014.c | 16 +- drivers/media/video/gspca/stv0680.c | 6 +- drivers/media/video/gspca/stv06xx/Makefile | 2 +- drivers/media/video/gspca/stv06xx/stv06xx.c | 18 +- drivers/media/video/gspca/stv06xx/stv06xx.h | 6 +- drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c | 10 +- drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c | 4 +- drivers/media/video/gspca/stv06xx/stv06xx_st6422.c | 4 +- drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c | 32 +- drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h | 56 +- drivers/media/video/gspca/sunplus.c | 13 +- drivers/media/video/gspca/t613.c | 14 +- drivers/media/video/gspca/vc032x.c | 13 +- drivers/media/video/gspca/vicam.c | 12 +- drivers/media/video/gspca/w996Xcf.c | 8 +- drivers/media/video/gspca/xirlink_cit.c | 14 +- drivers/media/video/gspca/zc3xx.c | 15 +- drivers/media/video/hdpvr/Makefile | 4 +- drivers/media/video/hdpvr/hdpvr-core.c | 25 +- drivers/media/video/hdpvr/hdpvr-i2c.c | 1 + drivers/media/video/hdpvr/hdpvr-video.c | 2 - drivers/media/video/hdpvr/hdpvr.h | 6 - drivers/media/video/ivtv/Makefile | 8 +- drivers/media/video/ivtv/ivtv-driver.c | 2 + drivers/media/video/ivtv/ivtv-driver.h | 1 - drivers/media/video/ivtv/ivtv-fileops.c | 19 +- drivers/media/video/ivtv/ivtv-ioctl.c | 20 +- drivers/media/video/ivtv/ivtv-version.h | 7 +- drivers/media/video/m5mols/Kconfig | 3 +- drivers/media/video/m5mols/Makefile | 2 +- drivers/media/video/m5mols/m5mols.h | 563 +- drivers/media/video/m5mols/m5mols_capture.c | 2 - drivers/media/video/m5mols/m5mols_controls.c | 369 +- drivers/media/video/m5mols/m5mols_core.c | 1795 ++---- drivers/media/video/m5mols/m5mols_reg.h | 390 +- drivers/media/video/omap/Kconfig | 7 +- drivers/media/video/omap/Makefile | 1 + drivers/media/video/omap/omap_vout.c | 707 +-- drivers/media/video/omap/omap_voutdef.h | 78 + drivers/media/video/omap/omap_voutlib.c | 46 + drivers/media/video/omap/omap_voutlib.h | 12 +- drivers/media/video/omap3isp/Makefile | 4 +- drivers/media/video/omap3isp/isp.c | 55 +- drivers/media/video/omap3isp/isp.h | 84 +- drivers/media/video/omap3isp/ispccdc.c | 131 +- drivers/media/video/omap3isp/ispccp2.c | 150 +- drivers/media/video/omap3isp/ispccp2.h | 1 + drivers/media/video/omap3isp/ispcsi2.c | 91 +- drivers/media/video/omap3isp/isph3a_aewb.c | 2 +- drivers/media/video/omap3isp/isph3a_af.c | 2 +- drivers/media/video/omap3isp/isphist.c | 2 +- drivers/media/video/omap3isp/isppreview.c | 419 +- drivers/media/video/omap3isp/isppreview.h | 9 +- drivers/media/video/omap3isp/ispqueue.c | 4 + drivers/media/video/omap3isp/ispreg.h | 3 - drivers/media/video/omap3isp/ispresizer.c | 104 +- drivers/media/video/omap3isp/ispstat.c | 68 +- drivers/media/video/omap3isp/ispstat.h | 2 +- drivers/media/video/omap3isp/ispvideo.c | 39 +- drivers/media/video/omap3isp/ispvideo.h | 4 +- drivers/media/video/pvrusb2/Makefile | 8 +- drivers/media/video/pvrusb2/pvrusb2-devattr.c | 1 + drivers/media/video/pvrusb2/pvrusb2-hdw.c | 8 + drivers/media/video/pvrusb2/pvrusb2-hdw.h | 3 + drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | 1 + drivers/media/video/pvrusb2/pvrusb2-main.c | 1 + drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 18 +- drivers/media/video/saa7134/Makefile | 8 +- drivers/media/video/saa7134/saa7134-alsa.c | 2 + drivers/media/video/saa7134/saa7134-cards.c | 13 +- drivers/media/video/saa7134/saa7134-core.c | 12 +- drivers/media/video/saa7134/saa7134-dvb.c | 25 + drivers/media/video/saa7134/saa7134-empress.c | 1 - drivers/media/video/saa7134/saa7134-video.c | 2 - drivers/media/video/saa7134/saa7134.h | 15 +- drivers/media/video/saa7164/Makefile | 10 +- drivers/media/video/saa7164/saa7164-cards.c | 62 + drivers/media/video/saa7164/saa7164-core.c | 4 +- drivers/media/video/saa7164/saa7164-dvb.c | 1 + drivers/media/video/saa7164/saa7164-encoder.c | 6 +- drivers/media/video/saa7164/saa7164-vbi.c | 6 +- drivers/media/video/saa7164/saa7164.h | 2 +- drivers/media/video/sn9c102/sn9c102.h | 1 - drivers/media/video/sn9c102/sn9c102_core.c | 16 +- drivers/media/video/tlg2300/Makefile | 8 +- drivers/media/video/tlg2300/pd-common.h | 1 - drivers/media/video/tlg2300/pd-dvb.c | 2 +- drivers/media/video/tlg2300/pd-main.c | 1 + drivers/media/video/tlg2300/pd-radio.c | 2 - drivers/media/video/usbvision/Makefile | 4 +- drivers/media/video/usbvision/usbvision-cards.c | 1 + drivers/media/video/usbvision/usbvision-video.c | 12 +- drivers/media/video/uvc/uvc_ctrl.c | 12 +- drivers/media/video/uvc/uvc_driver.c | 40 +- drivers/media/video/uvc/uvc_queue.c | 2 +- drivers/media/video/uvc/uvc_v4l2.c | 60 +- drivers/media/video/uvc/uvc_video.c | 39 +- drivers/media/video/uvc/uvcvideo.h | 107 +- drivers/media/video/zoran/zoran.h | 4 - drivers/media/video/zoran/zoran_card.c | 7 +- drivers/media/video/zoran/zoran_driver.c | 3 - drivers/memstick/core/memstick.c | 1 + drivers/memstick/core/mspro_block.c | 4 +- drivers/memstick/host/jmb38x_ms.c | 1 + drivers/memstick/host/tifm_ms.c | 1 + drivers/message/fusion/mptbase.c | 92 +- drivers/message/fusion/mptbase.h | 72 +- drivers/message/fusion/mptsas.c | 47 +- drivers/message/fusion/mptscsih.c | 20 +- drivers/message/fusion/mptscsih.h | 1 + drivers/message/i2o/i2o_scsi.c | 2 +- drivers/message/i2o/iop.c | 8 +- drivers/message/i2o/pci.c | 1 + drivers/misc/lis3lv02d/lis3lv02d.c | 389 +- drivers/misc/lis3lv02d/lis3lv02d.h | 9 +- drivers/misc/lis3lv02d/lis3lv02d_i2c.c | 45 +- drivers/misc/lis3lv02d/lis3lv02d_spi.c | 2 +- drivers/misc/sgi-gru/grukservices.c | 1 + drivers/misc/ti-st/st_core.c | 10 +- drivers/misc/ti-st/st_kim.c | 34 + drivers/misc/ti-st/st_ll.c | 19 + drivers/mtd/chips/cfi_cmdset_0002.c | 31 +- drivers/mtd/chips/fwh_lock.h | 3 +- drivers/mtd/chips/jedec_probe.c | 34 +- drivers/mtd/devices/Kconfig | 13 +- drivers/mtd/devices/Makefile | 3 + drivers/mtd/devices/doc2000.c | 17 +- drivers/mtd/devices/doc2001.c | 11 +- drivers/mtd/devices/doc2001plus.c | 11 +- drivers/mtd/devices/docecc.c | 2 +- drivers/mtd/devices/docprobe.c | 5 - drivers/mtd/devices/lart.c | 18 +- drivers/mtd/devices/m25p80.c | 111 +- drivers/mtd/devices/mtd_dataflash.c | 91 +- drivers/mtd/devices/sst25l.c | 46 +- drivers/mtd/lpddr/lpddr_cmds.c | 1 + drivers/mtd/onenand/generic.c | 14 +- drivers/mtd/onenand/omap2.c | 18 +- drivers/mtd/onenand/onenand_base.c | 114 +- drivers/mtd/onenand/onenand_bbt.c | 9 +- drivers/mtd/onenand/samsung.c | 13 +- drivers/mtd/tests/mtd_oobtest.c | 33 +- drivers/mtd/tests/mtd_pagetest.c | 37 +- drivers/mtd/tests/mtd_readtest.c | 13 +- drivers/mtd/tests/mtd_speedtest.c | 17 +- drivers/mtd/tests/mtd_stresstest.c | 11 +- drivers/mtd/tests/mtd_subpagetest.c | 17 +- drivers/mtd/tests/mtd_torturetest.c | 11 +- drivers/mtd/ubi/build.c | 28 +- drivers/mtd/ubi/cdev.c | 12 +- drivers/mtd/ubi/debug.c | 269 +- drivers/mtd/ubi/debug.h | 115 +- drivers/mtd/ubi/eba.c | 5 +- drivers/mtd/ubi/io.c | 44 +- drivers/mtd/ubi/kapi.c | 2 +- drivers/mtd/ubi/misc.c | 4 +- drivers/mtd/ubi/scan.c | 10 +- drivers/mtd/ubi/ubi.h | 8 +- drivers/mtd/ubi/upd.c | 10 +- drivers/mtd/ubi/vmt.c | 3 +- drivers/mtd/ubi/vtbl.c | 22 +- drivers/mtd/ubi/wl.c | 44 +- drivers/net/appletalk/cops.c | 2 +- drivers/net/appletalk/ltpc.c | 10 +- drivers/net/arcnet/Kconfig | 12 +- drivers/net/arcnet/Makefile | 1 + drivers/net/arcnet/arc-rimi.c | 1 + drivers/net/arcnet/com20020-isa.c | 1 + drivers/net/arcnet/com20020-pci.c | 1 + drivers/net/arcnet/com20020.c | 3 +- drivers/net/arcnet/com90io.c | 1 + drivers/net/arcnet/com90xx.c | 1 + drivers/net/bonding/bond_3ad.c | 71 +- drivers/net/bonding/bond_3ad.h | 9 +- drivers/net/bonding/bond_alb.c | 17 +- drivers/net/bonding/bond_debugfs.c | 2 +- drivers/net/bonding/bond_ipv6.c | 8 +- drivers/net/bonding/bond_main.c | 485 +- drivers/net/bonding/bond_procfs.c | 14 +- drivers/net/bonding/bond_sysfs.c | 219 +- drivers/net/bonding/bonding.h | 17 +- drivers/net/caif/Kconfig | 9 + drivers/net/caif/Makefile | 3 + drivers/net/caif/caif_serial.c | 2 +- drivers/net/caif/caif_shm_u5500.c | 1 - drivers/net/caif/caif_shmcore.c | 2 +- drivers/net/caif/caif_spi.c | 5 - drivers/net/caif/caif_spi_slave.c | 1 - drivers/net/can/Kconfig | 8 +- drivers/net/can/at91_can.c | 376 +- drivers/net/can/bfin_can.c | 137 +- drivers/net/can/c_can/c_can.c | 14 +- drivers/net/can/c_can/c_can_platform.c | 2 - drivers/net/can/dev.c | 41 +- drivers/net/can/flexcan.c | 243 +- drivers/net/can/janz-ican3.c | 1 + drivers/net/can/mscan/mscan.c | 37 +- drivers/net/can/sja1000/Kconfig | 14 + drivers/net/can/sja1000/Makefile | 2 + drivers/net/can/sja1000/plx_pci.c | 8 +- drivers/net/can/sja1000/sja1000.c | 34 +- drivers/net/can/sja1000/sja1000.h | 5 +- drivers/net/can/sja1000/sja1000_of_platform.c | 34 +- drivers/net/can/slcan.c | 67 +- drivers/net/can/softing/softing_fw.c | 1 + drivers/net/can/softing/softing_main.c | 4 +- drivers/net/can/ti_hecc.c | 4 +- drivers/net/can/usb/esd_usb2.c | 1 + drivers/net/can/vcan.c | 2 - drivers/net/cris/eth_v10.c | 2 +- drivers/net/hamradio/6pack.c | 2 +- drivers/net/hamradio/baycom_ser_fdx.c | 1 + drivers/net/hamradio/baycom_ser_hdx.c | 1 + drivers/net/hamradio/dmascc.c | 2 +- drivers/net/hamradio/hdlcdrv.c | 2 + drivers/net/hamradio/yam.c | 1 + drivers/net/irda/Kconfig | 4 +- drivers/net/irda/ali-ircc.c | 1 + drivers/net/irda/donauboe.c | 1 + drivers/net/irda/nsc-ircc.c | 1 + drivers/net/irda/pxaficp_ir.c | 2 + drivers/net/irda/sh_irda.c | 126 +- drivers/net/irda/sh_sir.c | 4 +- drivers/net/irda/sir_dev.c | 1 + drivers/net/irda/smsc-ircc2.c | 19 +- drivers/net/irda/toim3232-sir.c | 2 +- drivers/net/irda/via-ircc.c | 1 + drivers/net/irda/via-ircc.h | 2 +- drivers/net/irda/vlsi_ir.c | 1 + drivers/net/irda/w83977af_ir.c | 1 + drivers/net/phy/broadcom.c | 2 +- drivers/net/phy/dp83640.c | 209 +- drivers/net/phy/icplus.c | 103 +- drivers/net/phy/national.c | 17 +- drivers/net/phy/phy.c | 2 +- drivers/net/phy/phy_device.c | 4 +- drivers/net/phy/realtek.c | 1 + drivers/net/phy/vitesse.c | 34 +- drivers/net/tokenring/3c359.c | 8 +- drivers/net/tokenring/Kconfig | 15 +- drivers/net/tokenring/Makefile | 21 +- drivers/net/tokenring/ibmtr.c | 5 +- drivers/net/tokenring/lanstreamer.c | 2 +- drivers/net/tokenring/madgemc.c | 2 +- drivers/net/tokenring/olympic.c | 2 +- drivers/net/tokenring/smctr.c | 2 +- drivers/net/tokenring/tms380tr.c | 2 +- drivers/net/vmxnet3/vmxnet3_drv.c | 194 +- drivers/net/vmxnet3/vmxnet3_ethtool.c | 55 +- drivers/net/vmxnet3/vmxnet3_int.h | 8 +- drivers/net/wan/c101.c | 30 +- drivers/net/wan/cosa.c | 226 +- drivers/net/wan/cycx_drv.c | 81 +- drivers/net/wan/cycx_main.c | 32 +- drivers/net/wan/cycx_x25.c | 177 +- drivers/net/wan/dlci.c | 22 +- drivers/net/wan/dscc4.c | 81 +- drivers/net/wan/farsync.c | 9 +- drivers/net/wan/hd64570.c | 8 +- drivers/net/wan/hd64572.c | 8 +- drivers/net/wan/hdlc.c | 16 +- drivers/net/wan/hdlc_cisco.c | 21 +- drivers/net/wan/hdlc_fr.c | 96 +- drivers/net/wan/hdlc_ppp.c | 23 +- drivers/net/wan/hdlc_x25.c | 28 +- drivers/net/wan/hostess_sv11.c | 11 +- drivers/net/wan/ixp4xx_hss.c | 28 +- drivers/net/wan/lapbether.c | 21 +- drivers/net/wan/lmc/lmc_var.h | 2 +- drivers/net/wan/n2.c | 42 +- drivers/net/wan/pc300_drv.c | 4 +- drivers/net/wan/pc300_tty.c | 2 +- drivers/net/wan/pc300too.c | 36 +- drivers/net/wan/pci200syn.c | 29 +- drivers/net/wan/sbni.c | 74 +- drivers/net/wan/sdla.c | 52 +- drivers/net/wan/sealevel.c | 11 +- drivers/net/wan/wanxl.c | 94 +- drivers/net/wan/x25_asy.c | 50 +- drivers/net/wan/z85230.c | 34 +- drivers/net/wimax/i2400m/control.c | 2 + drivers/net/wimax/i2400m/debugfs.c | 1 + drivers/net/wimax/i2400m/fw.c | 1 + drivers/net/wimax/i2400m/i2400m.h | 2 +- drivers/net/wimax/i2400m/netdev.c | 1 + drivers/net/wimax/i2400m/rx.c | 2 + drivers/net/wimax/i2400m/sdio.c | 1 + drivers/net/wimax/i2400m/tx.c | 1 + drivers/net/wimax/i2400m/usb-rx.c | 2 +- drivers/net/wimax/i2400m/usb.c | 5 +- drivers/net/wireless/ath/ath5k/ahb.c | 50 +- drivers/net/wireless/ath/ath5k/ani.c | 90 +- drivers/net/wireless/ath/ath5k/ani.h | 4 + drivers/net/wireless/ath/ath5k/ath5k.h | 486 +- drivers/net/wireless/ath/ath5k/attach.c | 71 +- drivers/net/wireless/ath/ath5k/base.c | 1226 ++-- drivers/net/wireless/ath/ath5k/base.h | 263 +- drivers/net/wireless/ath/ath5k/caps.c | 51 +- drivers/net/wireless/ath/ath5k/debug.c | 439 +- drivers/net/wireless/ath/ath5k/debug.h | 25 +- drivers/net/wireless/ath/ath5k/desc.c | 11 +- drivers/net/wireless/ath/ath5k/desc.h | 4 +- drivers/net/wireless/ath/ath5k/dma.c | 21 +- drivers/net/wireless/ath/ath5k/eeprom.c | 60 +- drivers/net/wireless/ath/ath5k/eeprom.h | 12 +- drivers/net/wireless/ath/ath5k/gpio.c | 1 - drivers/net/wireless/ath/ath5k/initvals.c | 17 +- drivers/net/wireless/ath/ath5k/led.c | 75 +- drivers/net/wireless/ath/ath5k/mac80211-ops.c | 274 +- drivers/net/wireless/ath/ath5k/pci.c | 53 +- drivers/net/wireless/ath/ath5k/pcu.c | 45 +- drivers/net/wireless/ath/ath5k/phy.c | 222 +- drivers/net/wireless/ath/ath5k/qcu.c | 25 +- drivers/net/wireless/ath/ath5k/reg.h | 89 +- drivers/net/wireless/ath/ath5k/reset.c | 166 +- drivers/net/wireless/ath/ath5k/rfbuffer.h | 4 +- drivers/net/wireless/ath/ath5k/rfgain.h | 8 +- drivers/net/wireless/ath/ath5k/rfkill.c | 67 +- drivers/net/wireless/ath/ath5k/sysfs.c | 43 +- drivers/net/wireless/ath/ath5k/trace.h | 24 +- drivers/net/wireless/ath/ath9k/Kconfig | 10 +- drivers/net/wireless/ath/ath9k/Makefile | 3 +- drivers/net/wireless/ath/ath9k/ahb.c | 7 +- drivers/net/wireless/ath/ath9k/ani.c | 13 +- drivers/net/wireless/ath/ath9k/ani.h | 6 +- drivers/net/wireless/ath/ath9k/ar5008_initvals.h | 131 +- drivers/net/wireless/ath/ath9k/ar5008_phy.c | 48 +- drivers/net/wireless/ath/ath9k/ar9001_initvals.h | 266 +- drivers/net/wireless/ath/ath9k/ar9002_calib.c | 3 - drivers/net/wireless/ath/ath9k/ar9002_hw.c | 96 +- drivers/net/wireless/ath/ath9k/ar9002_initvals.h | 3403 ++++++----- drivers/net/wireless/ath/ath9k/ar9002_mac.c | 316 +- drivers/net/wireless/ath/ath9k/ar9002_phy.c | 34 +- .../net/wireless/ath/ath9k/ar9003_2p2_initvals.h | 210 +- drivers/net/wireless/ath/ath9k/ar9003_calib.c | 286 +- drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 369 +- drivers/net/wireless/ath/ath9k/ar9003_eeprom.h | 3 +- drivers/net/wireless/ath/ath9k/ar9003_hw.c | 657 +- drivers/net/wireless/ath/ath9k/ar9003_mac.c | 392 +- drivers/net/wireless/ath/ath9k/ar9003_paprd.c | 152 +- drivers/net/wireless/ath/ath9k/ar9003_phy.c | 188 +- drivers/net/wireless/ath/ath9k/ar9003_phy.h | 135 +- drivers/net/wireless/ath/ath9k/ath9k.h | 57 +- drivers/net/wireless/ath/ath9k/beacon.c | 106 +- drivers/net/wireless/ath/ath9k/btcoex.c | 9 +- drivers/net/wireless/ath/ath9k/calib.c | 21 +- drivers/net/wireless/ath/ath9k/calib.h | 4 + drivers/net/wireless/ath/ath9k/common.c | 32 +- drivers/net/wireless/ath/ath9k/common.h | 1 + drivers/net/wireless/ath/ath9k/debug.c | 573 +- drivers/net/wireless/ath/ath9k/debug.h | 69 +- drivers/net/wireless/ath/ath9k/eeprom.c | 7 +- drivers/net/wireless/ath/ath9k/eeprom.h | 17 +- drivers/net/wireless/ath/ath9k/eeprom_4k.c | 284 +- drivers/net/wireless/ath/ath9k/eeprom_9287.c | 181 +- drivers/net/wireless/ath/ath9k/eeprom_def.c | 253 +- drivers/net/wireless/ath/ath9k/gpio.c | 15 +- drivers/net/wireless/ath/ath9k/hif_usb.c | 11 +- drivers/net/wireless/ath/ath9k/htc.h | 4 +- drivers/net/wireless/ath/ath9k/htc_drv_beacon.c | 8 +- drivers/net/wireless/ath/ath9k/htc_drv_debug.c | 7 +- drivers/net/wireless/ath/ath9k/htc_drv_gpio.c | 10 +- drivers/net/wireless/ath/ath9k/htc_drv_init.c | 38 +- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 67 +- drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 18 +- drivers/net/wireless/ath/ath9k/hw-ops.h | 83 +- drivers/net/wireless/ath/ath9k/hw.c | 475 +- drivers/net/wireless/ath/ath9k/hw.h | 104 +- drivers/net/wireless/ath/ath9k/init.c | 138 +- drivers/net/wireless/ath/ath9k/mac.c | 70 +- drivers/net/wireless/ath/ath9k/mac.h | 57 +- drivers/net/wireless/ath/ath9k/main.c | 810 +-- drivers/net/wireless/ath/ath9k/pci.c | 60 +- drivers/net/wireless/ath/ath9k/rc.c | 101 +- drivers/net/wireless/ath/ath9k/rc.h | 8 +- drivers/net/wireless/ath/ath9k/recv.c | 340 +- drivers/net/wireless/ath/ath9k/reg.h | 127 +- drivers/net/wireless/ath/ath9k/xmit.c | 1236 ++-- drivers/net/wireless/ath/carl9170/Kconfig | 14 + drivers/net/wireless/ath/carl9170/carl9170.h | 38 +- drivers/net/wireless/ath/carl9170/cmd.c | 34 + drivers/net/wireless/ath/carl9170/cmd.h | 5 +- drivers/net/wireless/ath/carl9170/debug.c | 2 +- drivers/net/wireless/ath/carl9170/fw.c | 6 +- drivers/net/wireless/ath/carl9170/fwcmd.h | 30 +- drivers/net/wireless/ath/carl9170/fwdesc.h | 21 +- drivers/net/wireless/ath/carl9170/hw.h | 56 +- drivers/net/wireless/ath/carl9170/led.c | 2 +- drivers/net/wireless/ath/carl9170/mac.c | 129 - drivers/net/wireless/ath/carl9170/main.c | 257 +- drivers/net/wireless/ath/carl9170/phy.c | 28 +- drivers/net/wireless/ath/carl9170/rx.c | 2 +- drivers/net/wireless/ath/carl9170/tx.c | 309 +- drivers/net/wireless/ath/carl9170/usb.c | 31 +- drivers/net/wireless/ath/carl9170/version.h | 6 +- drivers/net/wireless/ath/carl9170/wlan.h | 25 +- drivers/net/wireless/b43/Kconfig | 48 +- drivers/net/wireless/b43/Makefile | 5 + drivers/net/wireless/b43/b43.h | 140 +- drivers/net/wireless/b43/debugfs.c | 2 +- drivers/net/wireless/b43/dma.c | 265 +- drivers/net/wireless/b43/dma.h | 26 +- drivers/net/wireless/b43/leds.c | 17 +- drivers/net/wireless/b43/lo.c | 8 +- drivers/net/wireless/b43/main.c | 866 ++- drivers/net/wireless/b43/main.h | 4 +- drivers/net/wireless/b43/pcmcia.c | 3 +- drivers/net/wireless/b43/phy_a.c | 23 +- drivers/net/wireless/b43/phy_common.c | 54 +- drivers/net/wireless/b43/phy_common.h | 8 + drivers/net/wireless/b43/phy_g.c | 94 +- drivers/net/wireless/b43/phy_lp.c | 137 +- drivers/net/wireless/b43/phy_n.c | 665 +- drivers/net/wireless/b43/phy_n.h | 4 + drivers/net/wireless/b43/pio.c | 40 +- drivers/net/wireless/b43/radio_2055.c | 3 +- drivers/net/wireless/b43/radio_2055.h | 5 + drivers/net/wireless/b43/radio_2056.c | 2 + drivers/net/wireless/b43/radio_2056.h | 31 +- drivers/net/wireless/b43/rfkill.c | 11 +- drivers/net/wireless/b43/sdio.c | 12 +- drivers/net/wireless/b43/sysfs.c | 6 +- drivers/net/wireless/b43/tables.c | 2 +- drivers/net/wireless/b43/tables_lpphy.c | 17 +- drivers/net/wireless/b43/tables_nphy.c | 3 +- drivers/net/wireless/b43/tables_nphy.h | 8 - drivers/net/wireless/b43/wa.c | 26 +- drivers/net/wireless/b43/xmit.c | 175 +- drivers/net/wireless/b43/xmit.h | 88 +- drivers/net/wireless/b43legacy/b43legacy.h | 25 +- drivers/net/wireless/b43legacy/debugfs.c | 2 +- drivers/net/wireless/b43legacy/dma.c | 387 +- drivers/net/wireless/b43legacy/dma.h | 109 +- drivers/net/wireless/b43legacy/ilt.c | 2 +- drivers/net/wireless/b43legacy/leds.c | 2 +- drivers/net/wireless/b43legacy/main.c | 23 +- drivers/net/wireless/b43legacy/main.h | 2 +- drivers/net/wireless/b43legacy/phy.c | 2 +- drivers/net/wireless/b43legacy/phy.h | 2 +- drivers/net/wireless/b43legacy/pio.c | 2 +- drivers/net/wireless/b43legacy/radio.c | 2 +- drivers/net/wireless/b43legacy/radio.h | 2 +- drivers/net/wireless/b43legacy/rfkill.c | 2 +- drivers/net/wireless/b43legacy/sysfs.c | 2 +- drivers/net/wireless/b43legacy/xmit.c | 4 +- drivers/net/wireless/hostap/hostap_80211_rx.c | 1 + drivers/net/wireless/hostap/hostap_80211_tx.c | 1 + drivers/net/wireless/hostap/hostap_ap.c | 2 + drivers/net/wireless/hostap/hostap_cs.c | 2 + drivers/net/wireless/hostap/hostap_info.c | 1 + drivers/net/wireless/hostap/hostap_ioctl.c | 1 + drivers/net/wireless/hostap/hostap_main.c | 6 +- drivers/net/wireless/hostap/hostap_proc.c | 1 + drivers/net/wireless/hostap/hostap_wlan.h | 1 + drivers/net/wireless/ipw2x00/ipw2100.c | 31 +- drivers/net/wireless/ipw2x00/ipw2200.c | 48 +- drivers/net/wireless/ipw2x00/ipw2200.h | 1 + drivers/net/wireless/ipw2x00/libipw_rx.c | 4 +- drivers/net/wireless/ipw2x00/libipw_tx.c | 2 +- drivers/net/wireless/ipw2x00/libipw_wx.c | 1 + drivers/net/wireless/iwlegacy/iwl-3945-led.c | 1 - drivers/net/wireless/iwlegacy/iwl-3945-rs.c | 1 - drivers/net/wireless/iwlegacy/iwl-3945.c | 5 - drivers/net/wireless/iwlegacy/iwl-4965-led.c | 1 - drivers/net/wireless/iwlegacy/iwl-4965-lib.c | 79 +- drivers/net/wireless/iwlegacy/iwl-4965-rs.c | 4 +- drivers/net/wireless/iwlegacy/iwl-4965-rx.c | 78 +- drivers/net/wireless/iwlegacy/iwl-4965-sta.c | 4 +- drivers/net/wireless/iwlegacy/iwl-4965-tx.c | 5 +- drivers/net/wireless/iwlegacy/iwl-4965.c | 11 +- drivers/net/wireless/iwlegacy/iwl-commands.h | 11 +- drivers/net/wireless/iwlegacy/iwl-core.c | 112 +- drivers/net/wireless/iwlegacy/iwl-core.h | 23 +- drivers/net/wireless/iwlegacy/iwl-debugfs.c | 193 +- drivers/net/wireless/iwlegacy/iwl-dev.h | 61 +- drivers/net/wireless/iwlegacy/iwl-devtrace.c | 3 - drivers/net/wireless/iwlegacy/iwl-devtrace.h | 60 - drivers/net/wireless/iwlegacy/iwl-eeprom.c | 1 - drivers/net/wireless/iwlegacy/iwl-helpers.h | 9 + drivers/net/wireless/iwlegacy/iwl-led.c | 1 - drivers/net/wireless/iwlegacy/iwl-rx.c | 22 +- drivers/net/wireless/iwlegacy/iwl-scan.c | 93 +- drivers/net/wireless/iwlegacy/iwl-sta.c | 1 + drivers/net/wireless/iwlegacy/iwl-tx.c | 1 + drivers/net/wireless/iwlegacy/iwl3945-base.c | 302 +- drivers/net/wireless/iwlegacy/iwl4965-base.c | 484 +- drivers/net/wireless/iwmc3200wifi/cfg80211.c | 6 +- drivers/net/wireless/iwmc3200wifi/commands.c | 1 + drivers/net/wireless/iwmc3200wifi/debugfs.c | 1 + drivers/net/wireless/iwmc3200wifi/fw.c | 2 +- drivers/net/wireless/iwmc3200wifi/main.c | 1 + drivers/net/wireless/iwmc3200wifi/sdio.c | 1 + drivers/net/wireless/libertas/README | 25 - drivers/net/wireless/libertas/cfg.c | 152 +- drivers/net/wireless/libertas/cfg.h | 2 + drivers/net/wireless/libertas/cmd.c | 52 +- drivers/net/wireless/libertas/cmd.h | 2 + drivers/net/wireless/libertas/cmdresp.c | 7 +- drivers/net/wireless/libertas/debugfs.c | 8 +- drivers/net/wireless/libertas/decl.h | 6 + drivers/net/wireless/libertas/dev.h | 32 +- drivers/net/wireless/libertas/ethtool.c | 2 + drivers/net/wireless/libertas/if_sdio.c | 313 +- drivers/net/wireless/libertas/if_spi.c | 14 +- drivers/net/wireless/libertas/if_usb.c | 36 +- drivers/net/wireless/libertas/main.c | 268 +- drivers/net/wireless/libertas/mesh.c | 1014 ++- drivers/net/wireless/libertas/mesh.h | 58 +- drivers/net/wireless/libertas/rx.c | 3 + drivers/net/wireless/libertas/tx.c | 5 +- drivers/net/wireless/libertas_tf/cmd.c | 2 + drivers/net/wireless/libertas_tf/deb_defs.h | 2 +- drivers/net/wireless/libertas_tf/if_usb.c | 2 +- drivers/net/wireless/libertas_tf/main.c | 4 +- drivers/net/wireless/mwifiex/11n.c | 36 +- drivers/net/wireless/mwifiex/11n.h | 14 +- drivers/net/wireless/mwifiex/11n_aggr.c | 55 +- drivers/net/wireless/mwifiex/11n_aggr.h | 1 + drivers/net/wireless/mwifiex/11n_rxreorder.c | 5 +- drivers/net/wireless/mwifiex/11n_rxreorder.h | 5 +- drivers/net/wireless/mwifiex/Kconfig | 11 + drivers/net/wireless/mwifiex/Makefile | 3 + drivers/net/wireless/mwifiex/cfg80211.c | 442 +- drivers/net/wireless/mwifiex/cfg80211.h | 3 +- drivers/net/wireless/mwifiex/cfp.c | 10 +- drivers/net/wireless/mwifiex/cmdevt.c | 83 +- drivers/net/wireless/mwifiex/debugfs.c | 35 +- drivers/net/wireless/mwifiex/decl.h | 13 +- drivers/net/wireless/mwifiex/fw.h | 62 +- drivers/net/wireless/mwifiex/init.c | 96 +- drivers/net/wireless/mwifiex/ioctl.h | 6 +- drivers/net/wireless/mwifiex/join.c | 58 +- drivers/net/wireless/mwifiex/main.c | 310 +- drivers/net/wireless/mwifiex/main.h | 135 +- drivers/net/wireless/mwifiex/scan.c | 1665 ++--- drivers/net/wireless/mwifiex/sdio.c | 116 +- drivers/net/wireless/mwifiex/sdio.h | 30 +- drivers/net/wireless/mwifiex/sta_cmd.c | 177 +- drivers/net/wireless/mwifiex/sta_cmdresp.c | 52 +- drivers/net/wireless/mwifiex/sta_event.c | 9 +- drivers/net/wireless/mwifiex/sta_ioctl.c | 339 +- drivers/net/wireless/mwifiex/sta_rx.c | 2 +- drivers/net/wireless/mwifiex/sta_tx.c | 15 +- drivers/net/wireless/mwifiex/txrx.c | 47 +- drivers/net/wireless/mwifiex/util.c | 5 +- drivers/net/wireless/mwifiex/util.h | 9 +- drivers/net/wireless/mwifiex/wmm.c | 38 +- drivers/net/wireless/orinoco/airport.c | 9 +- drivers/net/wireless/orinoco/cfg.c | 6 +- drivers/net/wireless/orinoco/fw.c | 8 +- drivers/net/wireless/orinoco/fw.h | 2 +- drivers/net/wireless/orinoco/hermes.c | 40 +- drivers/net/wireless/orinoco/hermes.h | 37 +- drivers/net/wireless/orinoco/hermes_dld.c | 8 +- drivers/net/wireless/orinoco/hermes_dld.h | 12 +- drivers/net/wireless/orinoco/hw.c | 48 +- drivers/net/wireless/orinoco/hw.h | 2 +- drivers/net/wireless/orinoco/main.c | 50 +- drivers/net/wireless/orinoco/mic.c | 8 +- drivers/net/wireless/orinoco/orinoco.h | 16 +- drivers/net/wireless/orinoco/orinoco_cs.c | 11 +- drivers/net/wireless/orinoco/orinoco_nortel.c | 3 +- drivers/net/wireless/orinoco/orinoco_pci.c | 4 +- drivers/net/wireless/orinoco/orinoco_plx.c | 6 +- drivers/net/wireless/orinoco/orinoco_tmd.c | 2 +- drivers/net/wireless/orinoco/orinoco_usb.c | 25 +- drivers/net/wireless/orinoco/spectrum_cs.c | 10 +- drivers/net/wireless/orinoco/wext.c | 15 +- drivers/net/wireless/p54/eeprom.c | 27 +- drivers/net/wireless/p54/fwio.c | 3 + drivers/net/wireless/p54/main.c | 117 +- drivers/net/wireless/p54/p54.h | 18 + drivers/net/wireless/p54/p54pci.c | 1 + drivers/net/wireless/p54/p54pci.h | 1 + drivers/net/wireless/p54/p54spi.c | 2 +- drivers/net/wireless/p54/p54usb.c | 1 + drivers/net/wireless/p54/txrx.c | 73 +- drivers/net/wireless/prism54/isl_ioctl.c | 2 +- drivers/net/wireless/prism54/islpci_dev.c | 8 +- drivers/net/wireless/prism54/islpci_dev.h | 1 + drivers/net/wireless/prism54/islpci_hotplug.c | 1 + drivers/net/wireless/rt2x00/Kconfig | 9 +- drivers/net/wireless/rt2x00/rt2400pci.c | 52 +- drivers/net/wireless/rt2x00/rt2500pci.c | 43 +- drivers/net/wireless/rt2x00/rt2500usb.c | 3 +- drivers/net/wireless/rt2x00/rt2800.h | 21 +- drivers/net/wireless/rt2x00/rt2800lib.c | 592 +- drivers/net/wireless/rt2x00/rt2800lib.h | 11 +- drivers/net/wireless/rt2x00/rt2800pci.c | 68 +- drivers/net/wireless/rt2x00/rt2800usb.c | 138 +- drivers/net/wireless/rt2x00/rt2x00.h | 38 +- drivers/net/wireless/rt2x00/rt2x00crypto.c | 6 +- drivers/net/wireless/rt2x00/rt2x00dev.c | 35 +- drivers/net/wireless/rt2x00/rt2x00lib.h | 6 +- drivers/net/wireless/rt2x00/rt2x00mac.c | 95 +- drivers/net/wireless/rt2x00/rt2x00queue.c | 180 +- drivers/net/wireless/rt2x00/rt2x00queue.h | 7 +- drivers/net/wireless/rt2x00/rt2x00usb.c | 1 + drivers/net/wireless/rt2x00/rt61pci.c | 45 +- drivers/net/wireless/rt2x00/rt73usb.c | 13 +- drivers/net/wireless/rtl818x/rtl8180/dev.c | 7 +- drivers/net/wireless/rtl818x/rtl8187/dev.c | 6 +- drivers/net/wireless/rtl818x/rtl8187/rtl8187.h | 10 +- drivers/net/wireless/rtlwifi/Kconfig | 17 +- drivers/net/wireless/rtlwifi/Makefile | 1 + drivers/net/wireless/rtlwifi/base.c | 284 +- drivers/net/wireless/rtlwifi/base.h | 2 + drivers/net/wireless/rtlwifi/cam.c | 9 +- drivers/net/wireless/rtlwifi/core.c | 30 +- drivers/net/wireless/rtlwifi/core.h | 2 + drivers/net/wireless/rtlwifi/debug.c | 2 - drivers/net/wireless/rtlwifi/debug.h | 5 - drivers/net/wireless/rtlwifi/efuse.c | 15 +- drivers/net/wireless/rtlwifi/pci.c | 318 +- drivers/net/wireless/rtlwifi/pci.h | 42 +- drivers/net/wireless/rtlwifi/ps.c | 99 +- drivers/net/wireless/rtlwifi/ps.h | 3 +- drivers/net/wireless/rtlwifi/rc.c | 2 +- drivers/net/wireless/rtlwifi/regd.c | 18 - drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c | 8 +- drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c | 10 +- drivers/net/wireless/rtlwifi/rtl8192c/main.c | 1 + drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c | 15 +- drivers/net/wireless/rtlwifi/rtl8192ce/def.h | 154 +- drivers/net/wireless/rtlwifi/rtl8192ce/hw.c | 53 +- drivers/net/wireless/rtlwifi/rtl8192ce/led.c | 2 +- drivers/net/wireless/rtlwifi/rtl8192ce/phy.c | 16 +- drivers/net/wireless/rtlwifi/rtl8192ce/reg.h | 6 +- drivers/net/wireless/rtlwifi/rtl8192ce/rf.c | 2 +- drivers/net/wireless/rtlwifi/rtl8192ce/sw.c | 80 +- drivers/net/wireless/rtlwifi/rtl8192ce/trx.c | 128 +- drivers/net/wireless/rtlwifi/rtl8192ce/trx.h | 6 - drivers/net/wireless/rtlwifi/rtl8192cu/def.h | 4 - drivers/net/wireless/rtlwifi/rtl8192cu/hw.c | 181 +- drivers/net/wireless/rtlwifi/rtl8192cu/led.c | 2 +- drivers/net/wireless/rtlwifi/rtl8192cu/mac.c | 32 +- drivers/net/wireless/rtlwifi/rtl8192cu/mac.h | 6 - drivers/net/wireless/rtlwifi/rtl8192cu/phy.c | 4 +- drivers/net/wireless/rtlwifi/rtl8192cu/rf.c | 31 +- drivers/net/wireless/rtlwifi/rtl8192cu/sw.c | 101 +- drivers/net/wireless/rtlwifi/rtl8192cu/trx.c | 36 +- drivers/net/wireless/rtlwifi/rtl8192se/def.h | 41 +- drivers/net/wireless/rtlwifi/rtl8192se/dm.c | 7 +- drivers/net/wireless/rtlwifi/rtl8192se/fw.c | 2 - drivers/net/wireless/rtlwifi/rtl8192se/hw.c | 84 +- drivers/net/wireless/rtlwifi/rtl8192se/led.c | 2 +- drivers/net/wireless/rtlwifi/rtl8192se/phy.c | 29 +- drivers/net/wireless/rtlwifi/rtl8192se/reg.h | 7 +- drivers/net/wireless/rtlwifi/rtl8192se/rf.c | 8 +- drivers/net/wireless/rtlwifi/rtl8192se/sw.c | 71 +- drivers/net/wireless/rtlwifi/rtl8192se/trx.c | 183 +- drivers/net/wireless/rtlwifi/usb.c | 161 +- drivers/net/wireless/rtlwifi/usb.h | 3 +- drivers/net/wireless/rtlwifi/wifi.h | 77 +- drivers/net/wireless/wl1251/acx.c | 6 +- drivers/net/wireless/wl1251/cmd.c | 2 +- drivers/net/wireless/wl1251/cmd.h | 2 +- drivers/net/wireless/wl1251/main.c | 3 +- drivers/net/wireless/wl1251/sdio.c | 1 + drivers/net/wireless/wl1251/spi.c | 1 + drivers/net/wireless/wl1251/wl12xx_80211.h | 2 +- drivers/net/wireless/wl12xx/Kconfig | 12 +- drivers/net/wireless/wl12xx/Makefile | 6 +- drivers/net/wireless/wl12xx/acx.c | 445 +- drivers/net/wireless/wl12xx/acx.h | 433 +- drivers/net/wireless/wl12xx/boot.c | 56 +- drivers/net/wireless/wl12xx/boot.h | 3 +- drivers/net/wireless/wl12xx/cmd.c | 889 ++- drivers/net/wireless/wl12xx/cmd.h | 410 +- drivers/net/wireless/wl12xx/conf.h | 452 +- drivers/net/wireless/wl12xx/debugfs.c | 216 +- drivers/net/wireless/wl12xx/event.c | 127 +- drivers/net/wireless/wl12xx/event.h | 71 +- drivers/net/wireless/wl12xx/ini.h | 3 + drivers/net/wireless/wl12xx/init.c | 142 +- drivers/net/wireless/wl12xx/io.c | 7 +- drivers/net/wireless/wl12xx/io.h | 16 +- drivers/net/wireless/wl12xx/main.c | 2031 ++++-- drivers/net/wireless/wl12xx/ps.c | 31 +- drivers/net/wireless/wl12xx/reg.h | 75 - drivers/net/wireless/wl12xx/rx.c | 102 +- drivers/net/wireless/wl12xx/rx.h | 30 +- drivers/net/wireless/wl12xx/scan.c | 271 +- drivers/net/wireless/wl12xx/scan.h | 49 +- drivers/net/wireless/wl12xx/sdio.c | 87 +- drivers/net/wireless/wl12xx/sdio_test.c | 17 +- drivers/net/wireless/wl12xx/spi.c | 20 +- drivers/net/wireless/wl12xx/testmode.c | 53 +- drivers/net/wireless/wl12xx/tx.c | 346 +- drivers/net/wireless/wl12xx/tx.h | 54 +- drivers/net/wireless/wl12xx/wl12xx.h | 217 +- drivers/net/wireless/wl12xx/wl12xx_80211.h | 27 +- drivers/net/wireless/zd1211rw/zd_chip.h | 2 + drivers/net/wireless/zd1211rw/zd_def.h | 6 + drivers/net/wireless/zd1211rw/zd_mac.c | 120 +- drivers/net/wireless/zd1211rw/zd_mac.h | 1 + drivers/net/wireless/zd1211rw/zd_usb.c | 130 +- drivers/net/wireless/zd1211rw/zd_usb.h | 5 +- drivers/net/xen-netback/common.h | 12 +- drivers/net/xen-netback/interface.c | 3 +- drivers/net/xen-netback/netback.c | 468 +- drivers/net/xen-netback/xenbus.c | 33 +- drivers/of/Kconfig | 8 +- drivers/of/Makefile | 1 + drivers/of/address.c | 49 +- drivers/of/base.c | 337 + drivers/of/fdt.c | 13 +- drivers/of/gpio.c | 16 +- drivers/of/irq.c | 122 +- drivers/of/of_mdio.c | 1 - drivers/of/of_net.c | 46 + drivers/of/of_pci.c | 114 +- drivers/of/of_spi.c | 1 + drivers/of/pdt.c | 8 + drivers/of/platform.c | 206 +- drivers/oprofile/event_buffer.c | 4 +- drivers/oprofile/oprofile_perf.c | 8 +- drivers/oprofile/oprofile_stats.h | 2 +- drivers/oprofile/oprofilefs.c | 6 +- drivers/parisc/ccio-dma.c | 1 + drivers/parisc/sba_iommu.c | 17 +- drivers/parport/parport_ax88796.c | 2 +- drivers/parport/parport_pc.c | 67 +- drivers/parport/parport_serial.c | 229 +- drivers/pci/Kconfig | 38 +- drivers/pci/Makefile | 8 +- drivers/pci/access.c | 61 +- drivers/pci/dmar.c | 1461 ----- drivers/pci/hotplug-pci.c | 1 + drivers/pci/hotplug.c | 2 +- drivers/pci/hotplug/acpi_pcihp.c | 6 +- drivers/pci/hotplug/acpiphp_glue.c | 136 +- drivers/pci/hotplug/cpci_hotplug_core.c | 2 +- drivers/pci/hotplug/cpqphp_core.c | 17 +- drivers/pci/hotplug/pciehp.h | 3 +- drivers/pci/hotplug/pciehp_acpi.c | 1 + drivers/pci/hotplug/pciehp_core.c | 27 +- drivers/pci/hotplug/pciehp_ctrl.c | 8 +- drivers/pci/hotplug/pciehp_hpc.c | 50 +- drivers/pci/hotplug/pcihp_slot.c | 48 +- drivers/pci/hotplug/rpadlpar_core.c | 3 +- drivers/pci/hotplug/shpchp.h | 3 +- drivers/pci/hotplug/shpchp_core.c | 36 +- drivers/pci/hotplug/shpchp_ctrl.c | 10 +- drivers/pci/hotplug/shpchp_sysfs.c | 21 +- drivers/pci/htirq.c | 1 + drivers/pci/intel-iommu.c | 4059 ------------ drivers/pci/intr_remapping.c | 798 --- drivers/pci/intr_remapping.h | 17 - drivers/pci/ioapic.c | 1 + drivers/pci/iov.c | 150 +- drivers/pci/iova.c | 435 -- drivers/pci/irq.c | 1 + drivers/pci/msi.c | 1 + drivers/pci/pci-acpi.c | 6 +- drivers/pci/pci-driver.c | 18 +- drivers/pci/pci-label.c | 2 +- drivers/pci/pci-sysfs.c | 3 +- drivers/pci/pci.c | 176 +- drivers/pci/pci.h | 6 +- drivers/pci/pcie/aer/aerdrv_core.c | 77 +- drivers/pci/pcie/aer/aerdrv_errprint.c | 3 +- drivers/pci/pcie/aspm.c | 2 +- drivers/pci/pcie/pme.c | 9 + drivers/pci/pcie/portdrv_pci.c | 1 - drivers/pci/probe.c | 250 +- drivers/pci/quirks.c | 161 +- drivers/pci/rom.c | 8 +- drivers/pci/setup-bus.c | 136 +- drivers/pci/setup-irq.c | 4 +- drivers/pci/setup-res.c | 9 +- drivers/pci/slot.c | 1 + drivers/pci/vpd.c | 1 + drivers/pci/xen-pcifront.c | 2 +- drivers/pcmcia/at91_cf.c | 11 +- drivers/pcmcia/db1xxx_ss.c | 1 + drivers/pcmcia/electra_cf.c | 4 +- drivers/pcmcia/pxa2xx_balloon3.c | 12 +- drivers/pcmcia/pxa2xx_base.c | 1 + drivers/pcmcia/pxa2xx_cm_x255.c | 12 +- drivers/pcmcia/pxa2xx_cm_x270.c | 12 +- drivers/pcmcia/pxa2xx_cm_x2xx.c | 3 +- drivers/pcmcia/pxa2xx_colibri.c | 11 - drivers/pcmcia/pxa2xx_mainstone.c | 10 - drivers/pcmcia/pxa2xx_palmld.c | 11 - drivers/pcmcia/pxa2xx_palmtc.c | 11 - drivers/pcmcia/pxa2xx_palmtx.c | 11 - drivers/pcmcia/pxa2xx_sharpsl.c | 3 - drivers/pcmcia/pxa2xx_stargate2.c | 34 +- drivers/pcmcia/pxa2xx_trizeps4.c | 4 - drivers/pcmcia/pxa2xx_viper.c | 10 - drivers/pcmcia/pxa2xx_vpac270.c | 2 +- drivers/pcmcia/rsrc_iodyn.c | 6 +- drivers/pcmcia/rsrc_nonstatic.c | 6 +- drivers/pcmcia/sa1100_simpad.c | 35 +- drivers/pcmcia/soc_common.c | 7 +- drivers/pcmcia/topic.h | 16 + drivers/platform/x86/Kconfig | 34 +- drivers/platform/x86/Makefile | 1 + drivers/platform/x86/acer-wmi.c | 427 +- drivers/platform/x86/acerhdf.c | 13 +- drivers/platform/x86/asus-laptop.c | 387 +- drivers/platform/x86/asus-nb-wmi.c | 27 +- drivers/platform/x86/asus-wmi.c | 233 +- drivers/platform/x86/asus-wmi.h | 7 + drivers/platform/x86/compal-laptop.c | 9 +- drivers/platform/x86/dell-laptop.c | 122 +- drivers/platform/x86/dell-wmi.c | 10 + drivers/platform/x86/eeepc-laptop.c | 2 +- drivers/platform/x86/eeepc-wmi.c | 27 + drivers/platform/x86/hp_accel.c | 14 +- drivers/platform/x86/ibm_rtl.c | 2 +- drivers/platform/x86/ideapad-laptop.c | 403 +- drivers/platform/x86/intel_ips.c | 4 +- drivers/platform/x86/intel_menlow.c | 2 + drivers/platform/x86/intel_mid_thermal.c | 26 +- drivers/platform/x86/intel_rar_register.c | 4 +- drivers/platform/x86/intel_scu_ipc.c | 3 +- drivers/platform/x86/intel_scu_ipcutil.c | 8 +- drivers/platform/x86/msi-laptop.c | 10 + drivers/platform/x86/msi-wmi.c | 6 +- drivers/platform/x86/samsung-laptop.c | 272 +- drivers/platform/x86/sony-laptop.c | 2 +- drivers/platform/x86/thinkpad_acpi.c | 15 +- drivers/platform/x86/topstar-laptop.c | 1 + drivers/platform/x86/toshiba_acpi.c | 652 +- drivers/platform/x86/wmi.c | 1 + drivers/pnp/pnpacpi/core.c | 1 + drivers/pnp/pnpacpi/rsparser.c | 40 +- drivers/pnp/pnpbios/rsparser.c | 12 +- drivers/pps/clients/Kconfig | 9 + drivers/pps/clients/Makefile | 1 + drivers/pps/clients/pps-ktimer.c | 12 - drivers/pps/clients/pps-ldisc.c | 10 +- drivers/pps/clients/pps_parport.c | 9 - drivers/pps/kapi.c | 20 +- drivers/pps/pps.c | 47 +- drivers/ps3/ps3-vuart.c | 2 +- drivers/ps3/ps3stor_lib.c | 3 +- drivers/ps3/sys-manager-core.c | 1 + drivers/rapidio/Kconfig | 6 +- drivers/rapidio/Makefile | 1 + drivers/rapidio/rio-scan.c | 6 +- drivers/rapidio/switches/idt_gen2.c | 1 + drivers/s390/block/dasd.c | 596 +- drivers/s390/block/dasd_eckd.c | 54 +- drivers/s390/block/dasd_eer.c | 2 +- drivers/s390/block/dasd_fba.c | 1 + drivers/s390/block/dasd_int.h | 59 +- drivers/s390/block/dasd_ioctl.c | 48 +- drivers/s390/block/dasd_proc.c | 110 +- drivers/s390/block/dcssblk.c | 7 +- drivers/s390/block/xpram.c | 5 +- drivers/s390/char/Kconfig | 3 - drivers/s390/char/con3215.c | 23 +- drivers/s390/char/fs3270.c | 3 +- drivers/s390/char/raw3270.c | 3 +- drivers/s390/char/sclp_async.c | 9 +- drivers/s390/char/sclp_cmd.c | 10 +- drivers/s390/char/sclp_cpi_sys.c | 1 + drivers/s390/char/sclp_quiesce.c | 5 +- drivers/s390/char/tape_34xx.c | 1 + drivers/s390/char/tape_3590.c | 1 + drivers/s390/char/tape_core.c | 2 - drivers/s390/char/vmcp.c | 1 + drivers/s390/char/vmlogrdr.c | 2 +- drivers/s390/char/vmur.c | 4 +- drivers/s390/char/vmwatchdog.c | 4 +- drivers/s390/char/zcore.c | 23 +- drivers/s390/cio/blacklist.c | 3 +- drivers/s390/cio/ccwgroup.c | 299 +- drivers/s390/cio/ccwreq.c | 23 +- drivers/s390/cio/chp.c | 2 + drivers/s390/cio/chsc.c | 7 +- drivers/s390/cio/chsc_sch.c | 5 +- drivers/s390/cio/cio.c | 27 +- drivers/s390/cio/cio.h | 5 + drivers/s390/cio/css.c | 112 +- drivers/s390/cio/css.h | 2 + drivers/s390/cio/device.c | 17 +- drivers/s390/cio/device.h | 15 +- drivers/s390/cio/device_fsm.c | 30 +- drivers/s390/cio/device_ops.c | 20 +- drivers/s390/cio/io_sch.h | 7 +- drivers/s390/cio/qdio.h | 52 +- drivers/s390/cio/qdio_debug.c | 27 +- drivers/s390/cio/qdio_main.c | 332 +- drivers/s390/cio/qdio_setup.c | 85 +- drivers/s390/cio/qdio_thinint.c | 140 +- drivers/s390/crypto/ap_bus.c | 123 +- drivers/s390/crypto/ap_bus.h | 22 +- drivers/s390/crypto/zcrypt_api.c | 2 +- drivers/s390/crypto/zcrypt_cex2a.c | 2 +- drivers/s390/crypto/zcrypt_mono.c | 2 +- drivers/s390/crypto/zcrypt_pcica.c | 2 +- drivers/s390/crypto/zcrypt_pcicc.c | 2 +- drivers/s390/crypto/zcrypt_pcixcc.c | 2 +- drivers/s390/kvm/kvm_virtio.c | 9 +- drivers/s390/net/Kconfig | 2 +- drivers/s390/net/claw.c | 3 +- drivers/s390/net/ctcm_main.c | 3 +- drivers/s390/net/ctcm_mpc.h | 1 + drivers/s390/net/ctcm_sysfs.c | 2 +- drivers/s390/net/fsm.h | 2 +- drivers/s390/net/lcs.c | 13 +- drivers/s390/net/netiucv.c | 2 + drivers/s390/net/qeth_core.h | 51 +- drivers/s390/net/qeth_core_main.c | 786 ++- drivers/s390/net/qeth_l2_main.c | 4 +- drivers/s390/net/qeth_l3.h | 4 + drivers/s390/net/qeth_l3_main.c | 195 +- drivers/s390/net/qeth_l3_sys.c | 114 +- drivers/s390/scsi/zfcp_aux.c | 1 + drivers/s390/scsi/zfcp_ccw.c | 1 + drivers/s390/scsi/zfcp_dbf.c | 37 + drivers/s390/scsi/zfcp_def.h | 7 + drivers/s390/scsi/zfcp_ext.h | 1 + drivers/s390/scsi/zfcp_fsf.c | 80 +- drivers/s390/scsi/zfcp_qdio.c | 63 +- drivers/s390/scsi/zfcp_qdio.h | 66 +- drivers/s390/scsi/zfcp_scsi.c | 24 +- drivers/sbus/char/bbc_envctrl.c | 6 + drivers/sbus/char/bbc_i2c.c | 38 +- drivers/sbus/char/display7seg.c | 15 +- drivers/sbus/char/envctrl.c | 12 +- drivers/sbus/char/flash.c | 12 +- drivers/sbus/char/uctrl.c | 12 +- drivers/scsi/aacraid/aachba.c | 1 + drivers/scsi/aacraid/commctrl.c | 3 +- drivers/scsi/aacraid/linit.c | 9 +- drivers/scsi/aacraid/src.c | 1 - drivers/scsi/aic7xxx/Kconfig.aic79xx | 3 +- drivers/scsi/aic7xxx/Kconfig.aic7xxx | 3 +- drivers/scsi/aic94xx/aic94xx_dump.c | 2 +- drivers/scsi/aic94xx/aic94xx_scb.c | 1 + drivers/scsi/aic94xx/aic94xx_task.c | 2 +- drivers/scsi/be2iscsi/be_cmds.c | 20 + drivers/scsi/be2iscsi/be_cmds.h | 2 + drivers/scsi/be2iscsi/be_iscsi.c | 60 +- drivers/scsi/be2iscsi/be_iscsi.h | 2 + drivers/scsi/be2iscsi/be_main.c | 315 +- drivers/scsi/be2iscsi/be_main.h | 9 +- drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h | 1162 ++-- drivers/scsi/bnx2fc/Kconfig | 3 +- drivers/scsi/bnx2fc/bnx2fc.h | 123 +- drivers/scsi/bnx2fc/bnx2fc_constants.h | 139 +- drivers/scsi/bnx2fc/bnx2fc_debug.h | 16 +- drivers/scsi/bnx2fc/bnx2fc_els.c | 444 +- drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 896 +-- drivers/scsi/bnx2fc/bnx2fc_hwi.c | 829 ++- drivers/scsi/bnx2fc/bnx2fc_io.c | 284 +- drivers/scsi/bnx2fc/bnx2fc_tgt.c | 92 +- drivers/scsi/bnx2i/57xx_iscsi_constants.h | 4 +- drivers/scsi/bnx2i/57xx_iscsi_hsi.h | 14 +- drivers/scsi/bnx2i/Kconfig | 3 +- drivers/scsi/bnx2i/bnx2i.h | 37 +- drivers/scsi/bnx2i/bnx2i_hwi.c | 218 +- drivers/scsi/bnx2i/bnx2i_init.c | 174 +- drivers/scsi/bnx2i/bnx2i_iscsi.c | 120 +- drivers/scsi/bnx2i/bnx2i_sysfs.c | 2 +- drivers/scsi/cxgbi/cxgb3i/Kbuild | 2 +- drivers/scsi/cxgbi/cxgb3i/Kconfig | 3 +- drivers/scsi/cxgbi/cxgb3i/cxgb3i.c | 25 +- drivers/scsi/cxgbi/cxgb4i/Kbuild | 2 +- drivers/scsi/cxgbi/cxgb4i/Kconfig | 3 +- drivers/scsi/cxgbi/cxgb4i/cxgb4i.c | 21 +- drivers/scsi/cxgbi/libcxgbi.c | 79 +- drivers/scsi/cxgbi/libcxgbi.h | 3 +- drivers/scsi/device_handler/scsi_dh.c | 62 +- drivers/scsi/device_handler/scsi_dh_alua.c | 109 +- drivers/scsi/device_handler/scsi_dh_emc.c | 1 + drivers/scsi/device_handler/scsi_dh_hp_sw.c | 1 + drivers/scsi/device_handler/scsi_dh_rdac.c | 91 +- drivers/scsi/dpt/dpti_i2o.h | 2 +- drivers/scsi/fcoe/fcoe.c | 407 +- drivers/scsi/fcoe/fcoe.h | 11 +- drivers/scsi/fcoe/fcoe_ctlr.c | 4 + drivers/scsi/fcoe/fcoe_transport.c | 108 +- drivers/scsi/fnic/fnic.h | 2 +- drivers/scsi/fnic/fnic_main.c | 21 +- drivers/scsi/fnic/fnic_scsi.c | 2 +- drivers/scsi/ibmvscsi/ibmvscsi.c | 3 +- drivers/scsi/ibmvscsi/rpa_vscsi.c | 10 + drivers/scsi/isci/host.c | 102 +- drivers/scsi/isci/host.h | 23 +- drivers/scsi/isci/init.c | 54 +- drivers/scsi/isci/phy.c | 13 +- drivers/scsi/isci/port.c | 148 +- drivers/scsi/isci/port.h | 6 +- drivers/scsi/isci/probe_roms.h | 4 +- drivers/scsi/isci/registers.h | 122 +- drivers/scsi/isci/remote_device.c | 109 +- drivers/scsi/isci/remote_device.h | 14 +- drivers/scsi/isci/request.c | 383 +- drivers/scsi/isci/request.h | 34 +- drivers/scsi/isci/task.c | 730 +-- drivers/scsi/isci/task.h | 54 +- drivers/scsi/libfc/fc_disc.c | 1 + drivers/scsi/libfc/fc_elsct.c | 1 + drivers/scsi/libfc/fc_exch.c | 111 +- drivers/scsi/libfc/fc_fcp.c | 41 +- drivers/scsi/libfc/fc_libfc.c | 1 + drivers/scsi/libfc/fc_lport.c | 95 +- drivers/scsi/libfc/fc_npiv.c | 1 + drivers/scsi/libfc/fc_rport.c | 15 +- drivers/scsi/libsas/sas_ata.c | 14 +- drivers/scsi/libsas/sas_discover.c | 19 +- drivers/scsi/libsas/sas_expander.c | 35 +- drivers/scsi/libsas/sas_host_smp.c | 104 +- drivers/scsi/libsas/sas_init.c | 43 +- drivers/scsi/libsas/sas_scsi_host.c | 146 +- drivers/scsi/libsas/sas_task.c | 1 + drivers/scsi/lpfc/lpfc.h | 27 +- drivers/scsi/lpfc/lpfc_attr.c | 88 +- drivers/scsi/lpfc/lpfc_bsg.c | 37 +- drivers/scsi/lpfc/lpfc_crtn.h | 14 +- drivers/scsi/lpfc/lpfc_ct.c | 3 + drivers/scsi/lpfc/lpfc_debugfs.c | 1633 ++++- drivers/scsi/lpfc/lpfc_debugfs.h | 125 +- drivers/scsi/lpfc/lpfc_els.c | 35 +- drivers/scsi/lpfc/lpfc_hbadisc.c | 227 +- drivers/scsi/lpfc/lpfc_hw.h | 8 +- drivers/scsi/lpfc/lpfc_hw4.h | 300 +- drivers/scsi/lpfc/lpfc_init.c | 296 +- drivers/scsi/lpfc/lpfc_logmsg.h | 1 + drivers/scsi/lpfc/lpfc_mbox.c | 80 +- drivers/scsi/lpfc/lpfc_scsi.c | 245 +- drivers/scsi/lpfc/lpfc_sli.c | 751 ++- drivers/scsi/lpfc/lpfc_sli.h | 18 +- drivers/scsi/lpfc/lpfc_sli4.h | 50 +- drivers/scsi/lpfc/lpfc_version.h | 2 +- drivers/scsi/lpfc/lpfc_vport.c | 16 +- drivers/scsi/megaraid/megaraid_mbox.c | 3 +- drivers/scsi/megaraid/megaraid_sas.h | 23 +- drivers/scsi/megaraid/megaraid_sas_base.c | 275 +- drivers/scsi/megaraid/megaraid_sas_fp.c | 27 +- drivers/scsi/megaraid/megaraid_sas_fusion.c | 193 +- drivers/scsi/megaraid/megaraid_sas_fusion.h | 19 +- drivers/scsi/mpt2sas/mpi/mpi2.h | 19 +- drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h | 225 +- drivers/scsi/mpt2sas/mpi/mpi2_init.h | 6 +- drivers/scsi/mpt2sas/mpi/mpi2_ioc.h | 115 +- drivers/scsi/mpt2sas/mpt2sas_base.c | 667 +- drivers/scsi/mpt2sas/mpt2sas_base.h | 88 +- drivers/scsi/mpt2sas/mpt2sas_config.c | 68 +- drivers/scsi/mpt2sas/mpt2sas_ctl.c | 40 +- drivers/scsi/mpt2sas/mpt2sas_scsih.c | 1004 ++- drivers/scsi/mpt2sas/mpt2sas_transport.c | 2 +- drivers/scsi/mvsas/Kconfig | 9 +- drivers/scsi/mvsas/mv_64xx.c | 101 +- drivers/scsi/mvsas/mv_94xx.c | 541 +- drivers/scsi/mvsas/mv_94xx.h | 99 +- drivers/scsi/mvsas/mv_chips.h | 17 +- drivers/scsi/mvsas/mv_defs.h | 13 +- drivers/scsi/mvsas/mv_init.c | 210 +- drivers/scsi/mvsas/mv_sas.c | 493 +- drivers/scsi/mvsas/mv_sas.h | 110 +- drivers/scsi/osd/Kconfig | 4 - drivers/scsi/osd/osd_initiator.c | 1 + drivers/scsi/pm8001/pm8001_hwi.c | 73 +- drivers/scsi/pm8001/pm8001_init.c | 4 +- drivers/scsi/pm8001/pm8001_sas.c | 93 +- drivers/scsi/pm8001/pm8001_sas.h | 4 +- drivers/scsi/qla2xxx/qla_attr.c | 322 +- drivers/scsi/qla2xxx/qla_bsg.c | 593 +- drivers/scsi/qla2xxx/qla_bsg.h | 42 + drivers/scsi/qla2xxx/qla_dbg.c | 398 +- drivers/scsi/qla2xxx/qla_dbg.h | 187 +- drivers/scsi/qla2xxx/qla_def.h | 14 +- drivers/scsi/qla2xxx/qla_dfs.c | 16 +- drivers/scsi/qla2xxx/qla_fw.h | 5 + drivers/scsi/qla2xxx/qla_gbl.h | 27 +- drivers/scsi/qla2xxx/qla_gs.c | 371 +- drivers/scsi/qla2xxx/qla_init.c | 889 +-- drivers/scsi/qla2xxx/qla_inline.h | 37 +- drivers/scsi/qla2xxx/qla_iocb.c | 410 +- drivers/scsi/qla2xxx/qla_isr.c | 784 +-- drivers/scsi/qla2xxx/qla_mbx.c | 1243 ++-- drivers/scsi/qla2xxx/qla_mid.c | 162 +- drivers/scsi/qla2xxx/qla_nx.c | 1565 ++++- drivers/scsi/qla2xxx/qla_nx.h | 259 +- drivers/scsi/qla2xxx/qla_os.c | 887 +-- drivers/scsi/qla2xxx/qla_sup.c | 275 +- drivers/scsi/qla2xxx/qla_version.h | 2 +- drivers/scsi/qla4xxx/Kconfig | 3 +- drivers/scsi/qla4xxx/Makefile | 2 +- drivers/scsi/qla4xxx/ql4_attr.c | 76 + drivers/scsi/qla4xxx/ql4_def.h | 263 +- drivers/scsi/qla4xxx/ql4_fw.h | 206 +- drivers/scsi/qla4xxx/ql4_glbl.h | 85 +- drivers/scsi/qla4xxx/ql4_init.c | 1015 +-- drivers/scsi/qla4xxx/ql4_iocb.c | 68 +- drivers/scsi/qla4xxx/ql4_isr.c | 83 +- drivers/scsi/qla4xxx/ql4_mbx.c | 835 ++- drivers/scsi/qla4xxx/ql4_nvram.c | 21 + drivers/scsi/qla4xxx/ql4_nx.c | 17 + drivers/scsi/qla4xxx/ql4_os.c | 5109 ++++++++++++---- drivers/scsi/qla4xxx/ql4_version.h | 2 +- drivers/scsi/sym53c8xx_2/sym_hipd.c | 4 + drivers/sfi/sfi_core.h | 3 + drivers/sh/Makefile | 8 + drivers/sh/clk/core.c | 123 +- drivers/sh/intc/chip.c | 12 +- drivers/sh/intc/core.c | 2 + drivers/sh/intc/dynamic.c | 1 + drivers/sh/intc/userimask.c | 1 + drivers/sh/intc/virq.c | 1 + drivers/sh/maple/maple.c | 1 + drivers/sh/pfc.c | 29 +- drivers/ssb/b43_pci_bridge.c | 3 +- drivers/ssb/driver_chipcommon.c | 3 +- drivers/ssb/driver_chipcommon_pmu.c | 7 +- drivers/ssb/driver_extif.c | 2 +- drivers/ssb/driver_gige.c | 16 +- drivers/ssb/driver_mipscore.c | 2 +- drivers/ssb/driver_pcicore.c | 13 +- drivers/ssb/embedded.c | 3 +- drivers/ssb/main.c | 59 +- drivers/ssb/pci.c | 11 +- drivers/ssb/pcihost_wrapper.c | 9 +- drivers/ssb/pcmcia.c | 2 +- drivers/ssb/scan.c | 5 +- drivers/ssb/sdio.c | 2 +- drivers/ssb/sprom.c | 2 +- drivers/staging/bcm/Bcmchar.c | 3182 +++++----- drivers/staging/bcm/Debug.h | 2 +- drivers/staging/bcm/InterfaceDld.c | 456 +- drivers/staging/bcm/InterfaceInit.c | 43 +- drivers/staging/bcm/InterfaceInit.h | 5 +- drivers/staging/bcm/InterfaceMisc.c | 304 +- drivers/staging/bcm/InterfaceRx.c | 4 +- drivers/staging/bcm/Macros.h | 337 +- drivers/staging/bcm/Misc.c | 1843 +++--- drivers/staging/bcm/PHSModule.c | 24 +- drivers/staging/bcm/PHSModule.h | 2 +- drivers/staging/bcm/headers.h | 10 +- drivers/staging/bcm/nvm.c | 13 +- drivers/staging/bcm/sort.c | 77 +- drivers/staging/comedi/Kconfig | 28 +- drivers/staging/comedi/comedi.h | 6 +- drivers/staging/comedi/comedi_compat32.c | 12 +- drivers/staging/comedi/comedi_fops.c | 43 +- drivers/staging/comedi/comedidev.h | 3 - drivers/staging/comedi/drivers.c | 4 + drivers/staging/comedi/drivers/Makefile | 2 + .../staging/comedi/drivers/addi-data/addi_common.c | 2 +- drivers/staging/comedi/drivers/adl_pci9118.c | 1 + drivers/staging/comedi/drivers/adv_pci1710.c | 17 +- drivers/staging/comedi/drivers/adv_pci1723.c | 2 +- drivers/staging/comedi/drivers/adv_pci_dio.c | 2 +- drivers/staging/comedi/drivers/c6xdigio.c | 13 +- drivers/staging/comedi/drivers/cb_das16_cs.c | 5 +- drivers/staging/comedi/drivers/cb_pcidas64.c | 123 +- drivers/staging/comedi/drivers/cb_pcidio.c | 21 +- drivers/staging/comedi/drivers/das08.c | 2 +- drivers/staging/comedi/drivers/das1800.c | 28 +- drivers/staging/comedi/drivers/dt282x.c | 1 + drivers/staging/comedi/drivers/ni_at_a2150.c | 1 + drivers/staging/comedi/drivers/ni_atmio.c | 10 +- drivers/staging/comedi/drivers/ni_daq_700.c | 10 +- drivers/staging/comedi/drivers/ni_labpc.c | 57 +- drivers/staging/comedi/drivers/ni_pcidio.c | 2 +- drivers/staging/comedi/drivers/ni_pcimio.c | 14 +- drivers/staging/comedi/drivers/pcl812.c | 1 + drivers/staging/comedi/drivers/pcl816.c | 1 + drivers/staging/comedi/drivers/pcl818.c | 1 + drivers/staging/comedi/drivers/pcmmio.c | 34 +- drivers/staging/comedi/drivers/pcmuio.c | 12 +- drivers/staging/comedi/drivers/rtd520.c | 22 +- drivers/staging/comedi/drivers/serial2002.c | 45 +- drivers/staging/comedi/drivers/ssv_dnp.c | 6 +- drivers/staging/comedi/drivers/unioxx5.c | 46 +- drivers/staging/comedi/drivers/usbdux.c | 7 +- drivers/staging/crystalhd/bc_dts_defs.h | 4 +- drivers/staging/crystalhd/bc_dts_glob_lnx.h | 6 +- drivers/staging/crystalhd/bc_dts_types.h | 57 - drivers/staging/crystalhd/crystalhd_cmds.h | 2 +- drivers/staging/crystalhd/crystalhd_fw_if.h | 532 +- drivers/staging/crystalhd/crystalhd_misc.h | 6 +- drivers/staging/cxt1e1/Kconfig | 3 +- drivers/staging/cxt1e1/linux.c | 7 +- drivers/staging/cxt1e1/sbecom_inline_linux.h | 65 - drivers/staging/echo/echo.c | 11 +- drivers/staging/ft1000/ft1000-pcmcia/ft1000.conf | 14 - drivers/staging/ft1000/ft1000-pcmcia/ft1000.h | 490 +- drivers/staging/ft1000/ft1000-pcmcia/ft1000_cs.c | 196 +- drivers/staging/ft1000/ft1000-pcmcia/ft1000_dev.h | 66 - drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c | 562 +- drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c | 244 +- drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c | 31 +- drivers/staging/ft1000/ft1000-usb/ft1000_hw.c | 11 +- drivers/staging/ft1000/ft1000-usb/ft1000_ioctl.h | 32 - drivers/staging/ft1000/ft1000-usb/ft1000_usb.h | 413 +- drivers/staging/iio/addac/Kconfig | 5 +- drivers/staging/iio/addac/adt7316-i2c.c | 3 +- drivers/staging/iio/addac/adt7316.c | 248 +- drivers/staging/iio/dac/Kconfig | 38 +- drivers/staging/iio/dac/Makefile | 3 + drivers/staging/iio/dac/ad5446.c | 126 +- drivers/staging/iio/dac/ad5446.h | 2 - drivers/staging/iio/dac/ad5504.c | 141 +- drivers/staging/iio/dac/ad5504.h | 2 - drivers/staging/iio/dac/ad5624r.h | 1 - drivers/staging/iio/dac/ad5624r_spi.c | 95 +- drivers/staging/iio/dac/ad5791.c | 246 +- drivers/staging/iio/dac/ad5791.h | 8 +- drivers/staging/iio/dac/dac.h | 2 +- drivers/staging/iio/dac/max517.c | 70 +- drivers/staging/iio/dds/Kconfig | 4 +- drivers/staging/iio/dds/ad5930.c | 39 +- drivers/staging/iio/dds/ad9832.c | 71 +- drivers/staging/iio/dds/ad9832.h | 2 - drivers/staging/iio/dds/ad9834.c | 92 +- drivers/staging/iio/dds/ad9834.h | 2 - drivers/staging/iio/dds/ad9850.c | 39 +- drivers/staging/iio/dds/ad9852.c | 41 +- drivers/staging/iio/dds/ad9910.c | 39 +- drivers/staging/iio/dds/ad9951.c | 39 +- drivers/staging/iio/imu/Kconfig | 16 +- drivers/staging/iio/imu/Makefile | 2 +- drivers/staging/iio/imu/adis16400.h | 9 +- drivers/staging/iio/imu/adis16400_core.c | 660 +- drivers/staging/iio/imu/adis16400_ring.c | 50 +- drivers/staging/iio/imu/adis16400_trigger.c | 17 +- drivers/staging/iio/light/Kconfig | 6 +- drivers/staging/iio/light/isl29018.c | 271 +- drivers/staging/iio/light/tsl2563.c | 176 +- drivers/staging/iio/light/tsl2583.c | 222 +- drivers/staging/iio/meter/Kconfig | 8 +- drivers/staging/iio/meter/Makefile | 2 +- drivers/staging/iio/meter/ade7753.c | 107 +- drivers/staging/iio/meter/ade7753.h | 10 +- drivers/staging/iio/meter/ade7754.c | 103 +- drivers/staging/iio/meter/ade7754.h | 12 +- drivers/staging/iio/meter/ade7758.h | 13 +- drivers/staging/iio/meter/ade7758_core.c | 81 +- drivers/staging/iio/meter/ade7758_ring.c | 58 +- drivers/staging/iio/meter/ade7758_trigger.c | 17 +- drivers/staging/iio/meter/ade7759.c | 101 +- drivers/staging/iio/meter/ade7759.h | 12 +- drivers/staging/iio/meter/ade7854-i2c.c | 40 +- drivers/staging/iio/meter/ade7854-spi.c | 41 +- drivers/staging/iio/meter/ade7854.c | 77 +- drivers/staging/iio/meter/ade7854.h | 36 +- drivers/staging/intel_sst/intel_sst.c | 16 +- .../staging/intel_sst/intel_sst_app_interface.c | 4 +- drivers/staging/intel_sst/intel_sst_common.h | 2 + .../staging/intel_sst/intel_sst_drv_interface.c | 11 + drivers/staging/intel_sst/intel_sst_dsp.c | 2 +- drivers/staging/intel_sst/intelmid.c | 1 + drivers/staging/intel_sst/intelmid_v2_control.c | 2 +- drivers/staging/line6/audio.c | 1 + drivers/staging/line6/pcm.c | 45 +- drivers/staging/mei/Kconfig | 2 +- drivers/staging/mei/TODO | 10 - drivers/staging/mei/init.c | 181 +- drivers/staging/mei/interface.c | 13 +- drivers/staging/mei/interface.h | 8 +- drivers/staging/mei/interrupt.c | 128 +- drivers/staging/mei/iorw.c | 32 +- drivers/staging/mei/main.c | 117 +- drivers/staging/mei/mei_dev.h | 155 +- drivers/staging/mei/wd.c | 254 +- drivers/staging/nvec/Kconfig | 12 +- drivers/staging/nvec/Makefile | 1 + drivers/staging/nvec/TODO | 16 +- drivers/staging/nvec/nvec-keytable.h | 225 +- drivers/staging/nvec/nvec.c | 959 ++- drivers/staging/nvec/nvec.h | 217 +- drivers/staging/nvec/nvec_kbd.c | 95 +- drivers/staging/nvec/nvec_power.c | 352 +- drivers/staging/nvec/nvec_ps2.c | 114 +- drivers/staging/octeon/ethernet-mdio.c | 27 +- drivers/staging/octeon/ethernet-rgmii.c | 34 +- drivers/staging/octeon/ethernet-rx.c | 29 +- drivers/staging/octeon/ethernet-sgmii.c | 14 +- drivers/staging/octeon/ethernet-spi.c | 1 + drivers/staging/octeon/ethernet-tx.c | 17 +- drivers/staging/octeon/ethernet-util.h | 4 - drivers/staging/octeon/ethernet-xaui.c | 22 +- drivers/staging/octeon/ethernet.c | 12 +- drivers/staging/olpc_dcon/olpc_dcon.c | 47 +- drivers/staging/panel/panel.c | 24 +- drivers/staging/pohmelfs/Kconfig | 8 - drivers/staging/pohmelfs/crypto.c | 1 + drivers/staging/pohmelfs/dir.c | 2 +- drivers/staging/pohmelfs/inode.c | 13 +- drivers/staging/pohmelfs/trans.c | 6 +- drivers/staging/rtl8187se/Makefile | 6 +- drivers/staging/rtl8187se/ieee80211/ieee80211.h | 6 +- .../staging/rtl8187se/ieee80211/ieee80211_crypt.c | 1 - .../rtl8187se/ieee80211/ieee80211_crypt_ccmp.c | 1 - .../rtl8187se/ieee80211/ieee80211_crypt_tkip.c | 1 - .../rtl8187se/ieee80211/ieee80211_crypt_wep.c | 1 - .../staging/rtl8187se/ieee80211/ieee80211_module.c | 1 - .../rtl8187se/ieee80211/ieee80211_softmac.c | 23 +- drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c | 2 +- drivers/staging/rtl8187se/r8180.h | 1 + drivers/staging/rtl8187se/r8180_core.c | 5 +- drivers/staging/rtl8187se/r8180_rtl8225z2.c | 4 +- drivers/staging/rtl8192u/ieee80211/Makefile | 109 - drivers/staging/rtl8192u/ieee80211/compress.c | 4 +- drivers/staging/rtl8192u/ieee80211/ieee80211.h | 6 +- .../staging/rtl8192u/ieee80211/ieee80211_crypt.c | 1 - .../rtl8192u/ieee80211/ieee80211_crypt_ccmp.c | 1 - .../rtl8192u/ieee80211/ieee80211_crypt_tkip.c | 1 - .../rtl8192u/ieee80211/ieee80211_crypt_wep.c | 1 - .../staging/rtl8192u/ieee80211/ieee80211_module.c | 3 +- drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c | 1 - .../staging/rtl8192u/ieee80211/ieee80211_softmac.c | 21 +- drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c | 2 +- drivers/staging/rtl8192u/r8192U.h | 1 - drivers/staging/rtl8192u/r8192U_core.c | 12 +- drivers/staging/rtl8712/Kconfig | 8 +- drivers/staging/rtl8712/basic_types.h | 25 + drivers/staging/rtl8712/big_endian.h | 25 + drivers/staging/rtl8712/drv_types.h | 41 +- drivers/staging/rtl8712/ethernet.h | 25 + drivers/staging/rtl8712/generic.h | 25 + drivers/staging/rtl8712/hal_init.c | 68 +- drivers/staging/rtl8712/ieee80211.c | 35 +- drivers/staging/rtl8712/ieee80211.h | 62 +- drivers/staging/rtl8712/if_ether.h | 25 + drivers/staging/rtl8712/little_endian.h | 25 + drivers/staging/rtl8712/mlme_osdep.h | 25 + drivers/staging/rtl8712/mp_custom_oid.h | 25 + drivers/staging/rtl8712/os_intfs.c | 42 +- drivers/staging/rtl8712/osdep_intf.h | 25 + drivers/staging/rtl8712/osdep_service.h | 70 +- drivers/staging/rtl8712/recv_linux.c | 6 +- drivers/staging/rtl8712/recv_osdep.h | 25 + drivers/staging/rtl8712/rtl8712_bitdef.h | 21 + drivers/staging/rtl8712/rtl8712_cmd.c | 18 + drivers/staging/rtl8712/rtl8712_cmd.h | 87 + drivers/staging/rtl8712/rtl8712_cmdctrl_bitdef.h | 19 + drivers/staging/rtl8712/rtl8712_cmdctrl_regdef.h | 19 + drivers/staging/rtl8712/rtl8712_debugctrl_bitdef.h | 19 + drivers/staging/rtl8712/rtl8712_debugctrl_regdef.h | 19 + .../staging/rtl8712/rtl8712_edcasetting_bitdef.h | 25 + .../staging/rtl8712/rtl8712_edcasetting_regdef.h | 19 + drivers/staging/rtl8712/rtl8712_efuse.c | 75 +- drivers/staging/rtl8712/rtl8712_event.h | 25 + drivers/staging/rtl8712/rtl8712_fifoctrl_bitdef.h | 19 + drivers/staging/rtl8712/rtl8712_fifoctrl_regdef.h | 19 + drivers/staging/rtl8712/rtl8712_gp_bitdef.h | 25 + drivers/staging/rtl8712/rtl8712_gp_regdef.h | 25 + drivers/staging/rtl8712/rtl8712_hal.h | 28 +- drivers/staging/rtl8712/rtl8712_interrupt_bitdef.h | 19 + drivers/staging/rtl8712/rtl8712_led.c | 2 +- .../staging/rtl8712/rtl8712_macsetting_bitdef.h | 19 + .../staging/rtl8712/rtl8712_macsetting_regdef.h | 19 + drivers/staging/rtl8712/rtl8712_powersave_bitdef.h | 19 + drivers/staging/rtl8712/rtl8712_powersave_regdef.h | 19 + drivers/staging/rtl8712/rtl8712_ratectrl_bitdef.h | 19 + drivers/staging/rtl8712/rtl8712_ratectrl_regdef.h | 25 + drivers/staging/rtl8712/rtl8712_recv.c | 25 +- drivers/staging/rtl8712/rtl8712_recv.h | 31 +- drivers/staging/rtl8712/rtl8712_regdef.h | 25 + drivers/staging/rtl8712/rtl8712_security_bitdef.h | 19 + drivers/staging/rtl8712/rtl8712_spec.h | 25 + drivers/staging/rtl8712/rtl8712_syscfg_bitdef.h | 25 + drivers/staging/rtl8712/rtl8712_syscfg_regdef.h | 25 + drivers/staging/rtl8712/rtl8712_timectrl_bitdef.h | 19 + drivers/staging/rtl8712/rtl8712_timectrl_regdef.h | 19 + drivers/staging/rtl8712/rtl8712_wmac_bitdef.h | 25 + drivers/staging/rtl8712/rtl8712_wmac_regdef.h | 25 + drivers/staging/rtl8712/rtl8712_xmit.c | 303 +- drivers/staging/rtl8712/rtl8712_xmit.h | 37 + drivers/staging/rtl8712/rtl871x_byteorder.h | 19 + drivers/staging/rtl8712/rtl871x_cmd.c | 172 +- drivers/staging/rtl8712/rtl871x_cmd.h | 77 +- drivers/staging/rtl8712/rtl871x_debug.h | 25 + drivers/staging/rtl8712/rtl871x_eeprom.h | 19 + drivers/staging/rtl8712/rtl871x_event.h | 25 + drivers/staging/rtl8712/rtl871x_ht.h | 25 + drivers/staging/rtl8712/rtl871x_io.h | 25 + drivers/staging/rtl8712/rtl871x_ioctl_linux.c | 298 +- drivers/staging/rtl8712/rtl871x_ioctl_rtl.h | 25 + drivers/staging/rtl8712/rtl871x_ioctl_set.c | 3 +- drivers/staging/rtl8712/rtl871x_ioctl_set.h | 27 +- drivers/staging/rtl8712/rtl871x_led.h | 25 + drivers/staging/rtl8712/rtl871x_mlme.c | 62 +- drivers/staging/rtl8712/rtl871x_mlme.h | 28 +- drivers/staging/rtl8712/rtl871x_mp.c | 26 +- drivers/staging/rtl8712/rtl871x_mp.h | 26 +- drivers/staging/rtl8712/rtl871x_mp_ioctl.h | 29 +- drivers/staging/rtl8712/rtl871x_pwrctrl.h | 25 + drivers/staging/rtl8712/rtl871x_recv.c | 17 +- drivers/staging/rtl8712/rtl871x_rf.h | 25 + drivers/staging/rtl8712/rtl871x_security.c | 15 + drivers/staging/rtl8712/rtl871x_security.h | 25 + drivers/staging/rtl8712/rtl871x_sta_mgt.c | 5 +- drivers/staging/rtl8712/rtl871x_wlan_sme.h | 25 + drivers/staging/rtl8712/rtl871x_xmit.c | 31 +- drivers/staging/rtl8712/rtl871x_xmit.h | 52 +- drivers/staging/rtl8712/sta_info.h | 33 +- drivers/staging/rtl8712/swab.h | 25 + drivers/staging/rtl8712/usb_intf.c | 38 +- drivers/staging/rtl8712/usb_ops.h | 25 + drivers/staging/rtl8712/usb_ops_linux.c | 29 +- drivers/staging/rtl8712/usb_osintf.h | 26 + drivers/staging/rtl8712/usb_vendor_req.h | 25 + drivers/staging/rtl8712/wifi.h | 32 +- drivers/staging/rtl8712/wlan_bssdef.h | 25 + drivers/staging/rtl8712/xmit_linux.c | 27 +- drivers/staging/rtl8712/xmit_osdep.h | 26 + drivers/staging/rts_pstor/Makefile | 2 +- drivers/staging/rts_pstor/ms.c | 3 +- drivers/staging/rts_pstor/rtsx.c | 172 +- drivers/staging/rts_pstor/rtsx.h | 20 +- drivers/staging/rts_pstor/rtsx_chip.c | 6 +- drivers/staging/rts_pstor/rtsx_scsi.c | 2 +- drivers/staging/rts_pstor/rtsx_transport.c | 11 +- drivers/staging/rts_pstor/sd.c | 99 +- drivers/staging/rts_pstor/sd.h | 5 + drivers/staging/rts_pstor/spi.c | 2 +- drivers/staging/sep/sep_driver.c | 13 +- drivers/staging/sep/sep_driver_config.h | 2 +- drivers/staging/serqt_usb2/serqt_usb2.c | 36 +- drivers/staging/slicoss/Kconfig | 2 +- drivers/staging/slicoss/slicoss.c | 2 +- drivers/staging/sm7xx/smtcfb.c | 2 + drivers/staging/speakup/devsynth.c | 5 +- drivers/staging/speakup/kobjects.c | 4 +- drivers/staging/speakup/main.c | 3 +- drivers/staging/speakup/speakup.h | 3 +- drivers/staging/speakup/speakup_soft.c | 11 +- drivers/staging/speakup/varhandlers.c | 4 +- drivers/staging/spectra/ffsport.c | 15 +- drivers/staging/spectra/lld_mtd.c | 6 +- drivers/staging/spectra/lld_nand.c | 18 +- drivers/staging/ste_rmi4/Makefile | 1 + drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c | 44 +- drivers/staging/ste_rmi4/synaptics_i2c_rmi4.h | 2 - drivers/staging/tidspbridge/Kconfig | 2 +- drivers/staging/tidspbridge/core/dsp-clock.c | 16 +- drivers/staging/tidspbridge/gen/gh.c | 2 +- drivers/staging/tidspbridge/hw/hw_mmu.c | 2 +- .../tidspbridge/include/dspbridge/host_os.h | 3 +- drivers/staging/tidspbridge/rmgr/drv_interface.c | 4 - drivers/staging/vme/boards/vme_vmivme7805.c | 4 +- drivers/staging/vme/bridges/vme_ca91cx42.c | 43 +- drivers/staging/vme/bridges/vme_tsi148.c | 26 +- drivers/staging/vme/devices/vme_user.c | 122 +- drivers/staging/vme/devices/vme_user.h | 8 +- drivers/staging/vme/vme.c | 349 +- drivers/staging/vme/vme.h | 52 +- drivers/staging/vme/vme_api.txt | 90 +- drivers/staging/vme/vme_bridge.h | 17 +- drivers/staging/vt6655/IEEE11h.c | 406 +- drivers/staging/vt6655/bssdb.c | 2 +- drivers/staging/vt6655/device_main.c | 23 +- drivers/staging/vt6655/dpc.c | 30 +- drivers/staging/vt6655/ioctl.c | 1092 ++-- drivers/staging/vt6655/rf.c | 1 + drivers/staging/vt6655/wmgr.c | 49 +- drivers/staging/vt6655/wpactl.c | 4 +- drivers/staging/vt6656/baseband.c | 3 - drivers/staging/vt6656/dpc.c | 30 +- drivers/staging/vt6656/ioctl.c | 1040 ++-- drivers/staging/vt6656/main_usb.c | 13 +- drivers/staging/vt6656/usbpipe.c | 28 +- drivers/staging/vt6656/wmgr.c | 49 +- drivers/staging/vt6656/wpactl.c | 18 +- drivers/staging/winbond/mds_s.h | 2 +- drivers/staging/winbond/phy_calibration.c | 470 +- drivers/staging/winbond/wb35reg_s.h | 2 +- drivers/staging/winbond/wbusb.c | 3 +- drivers/staging/wlags49_h2/Makefile | 26 - drivers/staging/wlags49_h2/debug.h | 61 +- drivers/staging/wlags49_h2/hcf.c | 6434 ++++++++++---------- drivers/staging/wlags49_h2/hcf.h | 10 - drivers/staging/wlags49_h2/hcfcfg.h | 1586 +---- drivers/staging/wlags49_h2/hcfdef.h | 857 ++- drivers/staging/wlags49_h2/mdd.h | 34 +- drivers/staging/wlags49_h2/wl_cs.c | 115 +- drivers/staging/wlags49_h2/wl_internal.h | 23 +- drivers/staging/wlags49_h2/wl_main.c | 6 +- drivers/staging/wlags49_h2/wl_netdev.c | 4 +- drivers/staging/wlags49_h2/wl_priv.c | 9 +- drivers/staging/wlags49_h2/wl_sysfs.c | 18 +- drivers/staging/wlags49_h2/wl_version.h | 7 +- drivers/staging/wlags49_h2/wl_wext.c | 1184 ++-- drivers/staging/wlags49_h2/wl_wext.h | 8 - drivers/staging/wlags49_h25/Makefile | 26 - drivers/staging/wlan-ng/p80211netdev.c | 2 +- drivers/staging/wlan-ng/prism2fw.c | 4 +- drivers/staging/wlan-ng/prism2sta.c | 1 - drivers/staging/xgifb/TODO | 1 - drivers/staging/xgifb/XGI_main.h | 238 +- drivers/staging/xgifb/XGI_main_26.c | 1452 ++--- drivers/staging/xgifb/XGIfb.h | 48 +- drivers/staging/xgifb/vb_def.h | 605 +- drivers/staging/xgifb/vb_ext.c | 1 - drivers/staging/xgifb/vb_ext.h | 20 - drivers/staging/xgifb/vb_init.c | 258 +- drivers/staging/xgifb/vb_init.h | 2 +- drivers/staging/xgifb/vb_setmode.c | 1542 +---- drivers/staging/xgifb/vb_struct.h | 97 +- drivers/staging/xgifb/vb_table.h | 1200 +--- drivers/staging/xgifb/vb_util.c | 5 +- drivers/staging/xgifb/vgatypes.h | 11 +- drivers/staging/zram/Kconfig | 7 - drivers/staging/zram/zram_drv.c | 607 +- drivers/staging/zram/zram_drv.h | 19 +- drivers/staging/zram/zram_sysfs.c | 85 +- drivers/target/loopback/Kconfig | 6 - drivers/target/loopback/tcm_loop.c | 285 +- drivers/target/loopback/tcm_loop.h | 6 - drivers/target/tcm_fc/Makefile | 17 +- drivers/target/tcm_fc/tcm_fc.h | 45 +- drivers/target/tcm_fc/tfc_cmd.c | 233 +- drivers/target/tcm_fc/tfc_conf.c | 82 +- drivers/target/tcm_fc/tfc_io.c | 246 +- drivers/target/tcm_fc/tfc_sess.c | 22 +- drivers/tty/hvc/Kconfig | 14 + drivers/tty/hvc/Makefile | 4 +- drivers/tty/hvc/hvc_console.c | 72 +- drivers/tty/hvc/hvc_console.h | 4 + drivers/tty/hvc/hvc_irq.c | 2 +- drivers/tty/hvc/hvc_iseries.c | 1 + drivers/tty/hvc/hvc_vio.c | 409 +- drivers/tty/hvc/hvc_xen.c | 2 +- drivers/tty/hvc/hvcs.c | 10 +- drivers/tty/hvc/hvsi.c | 131 +- drivers/tty/serial/cpm_uart/cpm_uart_core.c | 1 + drivers/tty/serial/jsm/jsm.h | 3 - drivers/tty/serial/jsm/jsm_driver.c | 20 +- drivers/tty/serial/jsm/jsm_neo.c | 2 +- drivers/tty/vt/consolemap.c | 2 + drivers/tty/vt/keyboard.c | 3 +- drivers/tty/vt/selection.c | 4 +- drivers/tty/vt/vc_screen.c | 1 + drivers/tty/vt/vt.c | 8 +- drivers/uio/uio.c | 30 +- drivers/uio/uio_pci_generic.c | 5 - drivers/uio/uio_pdrv.c | 3 +- drivers/uio/uio_pdrv_genirq.c | 46 +- drivers/usb/atm/ueagle-atm.c | 38 +- drivers/usb/atm/usbatm.c | 4 +- drivers/usb/c67x00/c67x00-drv.c | 1 + drivers/usb/host/whci/debug.c | 1 + drivers/usb/host/whci/hcd.c | 1 + drivers/usb/host/whci/init.c | 2 +- drivers/usb/image/microtek.c | 2 +- drivers/usb/mon/mon_bin.c | 1 + drivers/usb/mon/mon_stat.c | 1 + drivers/usb/mon/mon_text.c | 10 +- drivers/usb/musb/Kconfig | 81 +- drivers/usb/musb/Makefile | 4 +- drivers/usb/musb/am35x.c | 5 +- drivers/usb/musb/blackfin.c | 1 + drivers/usb/musb/blackfin.h | 2 +- drivers/usb/musb/cppi_dma.c | 1 + drivers/usb/musb/da8xx.c | 13 +- drivers/usb/musb/davinci.c | 8 - drivers/usb/musb/musb_core.c | 188 +- drivers/usb/musb/musb_core.h | 82 +- drivers/usb/musb/musb_debugfs.c | 6 - drivers/usb/musb/musb_gadget.c | 184 +- drivers/usb/musb/musb_gadget_ep0.c | 12 +- drivers/usb/musb/musb_host.c | 6 +- drivers/usb/musb/musb_host.h | 4 - drivers/usb/musb/musb_regs.h | 6 +- drivers/usb/musb/musb_virthub.c | 6 - drivers/usb/musb/musbhsdma.c | 2 +- drivers/usb/musb/omap2430.c | 15 +- drivers/usb/musb/tusb6010.c | 27 +- drivers/usb/musb/tusb6010_omap.c | 3 +- drivers/usb/musb/ux500_dma.c | 38 +- drivers/usb/renesas_usbhs/Kconfig | 15 +- drivers/usb/renesas_usbhs/Makefile | 10 +- drivers/usb/renesas_usbhs/common.c | 268 +- drivers/usb/renesas_usbhs/common.h | 104 +- drivers/usb/renesas_usbhs/mod.c | 81 +- drivers/usb/renesas_usbhs/mod.h | 61 +- drivers/usb/renesas_usbhs/mod_gadget.c | 930 +-- drivers/usb/renesas_usbhs/pipe.c | 472 +- drivers/usb/renesas_usbhs/pipe.h | 70 +- drivers/usb/wusbcore/cbaf.c | 4 +- drivers/usb/wusbcore/devconnect.c | 1 + drivers/usb/wusbcore/mmc.c | 1 + drivers/usb/wusbcore/rh.c | 1 + drivers/usb/wusbcore/security.c | 1 + drivers/usb/wusbcore/wa-hc.c | 3 +- drivers/usb/wusbcore/wa-rpipe.c | 8 +- drivers/usb/wusbcore/wa-xfer.c | 13 +- drivers/uwb/est.c | 1 + drivers/uwb/i1480/dfu/dfu.c | 1 + drivers/uwb/ie.c | 1 + drivers/uwb/lc-dev.c | 15 +- drivers/uwb/lc-rc.c | 1 + drivers/uwb/neh.c | 1 + drivers/uwb/pal.c | 1 + drivers/uwb/radio.c | 1 + drivers/uwb/reset.c | 1 + drivers/uwb/rsv.c | 1 + drivers/uwb/scan.c | 1 + drivers/uwb/umc-bus.c | 1 + drivers/uwb/umc-dev.c | 1 + drivers/uwb/umc-drv.c | 1 + drivers/uwb/uwb-internal.h | 1 - drivers/uwb/uwbd.c | 2 +- drivers/uwb/whc-rc.c | 2 +- drivers/uwb/whci.c | 1 + drivers/vhost/net.c | 112 +- drivers/vhost/test.c | 5 + drivers/vhost/vhost.c | 214 +- drivers/vhost/vhost.h | 34 +- drivers/video/aty/atyfb_base.c | 7 +- drivers/video/aty/mach64_accel.c | 3 +- drivers/video/aty/mach64_cursor.c | 22 +- drivers/video/aty/radeon_base.c | 10 +- drivers/video/console/bitblit.c | 3 +- drivers/video/console/fbcon_ccw.c | 3 +- drivers/video/console/fbcon_cw.c | 3 +- drivers/video/console/fbcon_ud.c | 3 +- drivers/video/console/vgacon.c | 81 +- drivers/video/i810/i810.h | 2 +- drivers/video/intelfb/intelfbhw.c | 6 +- drivers/video/logo/.gitignore | 7 + drivers/video/logo/logo.c | 17 +- drivers/video/matrox/matroxfb_accel.c | 38 +- drivers/video/matrox/matroxfb_base.h | 4 +- drivers/video/mb862xx/mb862xx-i2c.c | 3 +- drivers/video/mb862xx/mb862xxfbdrv.c | 11 +- drivers/video/mbx/mbxfb.c | 6 +- drivers/video/msm/mddi.c | 2 +- drivers/video/msm/mdp.c | 10 +- drivers/video/msm/msm_fb.c | 7 +- drivers/video/omap2/displays/Kconfig | 28 +- drivers/video/omap2/displays/Makefile | 3 + drivers/video/omap2/displays/panel-generic-dpi.c | 113 +- drivers/video/omap2/displays/panel-taal.c | 180 +- drivers/video/omap2/omapfb/Kconfig | 2 +- drivers/video/omap2/omapfb/omapfb-ioctl.c | 73 +- drivers/video/omap2/omapfb/omapfb-main.c | 302 +- drivers/video/omap2/omapfb/omapfb-sysfs.c | 40 +- drivers/video/omap2/omapfb/omapfb.h | 37 +- drivers/video/pnx4008/sdum.c | 2 +- drivers/video/riva/fbdev.c | 5 +- drivers/video/savage/savagefb_accel.c | 1 + drivers/video/savage/savagefb_driver.c | 16 +- drivers/video/sis/sis_main.c | 30 +- drivers/video/vermilion/vermilion.h | 2 +- drivers/video/via/dvi.c | 34 +- drivers/video/via/dvi.h | 3 +- drivers/video/via/global.c | 2 + drivers/video/via/global.h | 2 + drivers/video/via/hw.c | 548 +- drivers/video/via/hw.h | 285 +- drivers/video/via/lcd.c | 53 +- drivers/video/via/lcd.h | 7 +- drivers/video/via/share.h | 23 +- drivers/video/via/via-core.c | 2 +- drivers/video/via/via-gpio.c | 1 + drivers/video/via/via_modesetting.c | 104 + drivers/video/via/via_modesetting.h | 18 + drivers/video/via/viafbdev.c | 170 +- drivers/video/via/viamode.c | 60 +- drivers/video/via/viamode.h | 4 +- drivers/virtio/Kconfig | 14 + drivers/virtio/Makefile | 1 + drivers/virtio/virtio.c | 20 +- drivers/virtio/virtio_balloon.c | 7 + drivers/virtio/virtio_pci.c | 41 +- drivers/virtio/virtio_ring.c | 11 + drivers/w1/masters/ds2490.c | 4 +- drivers/w1/masters/matrox_w1.c | 6 +- drivers/w1/slaves/w1_ds2408.c | 2 +- drivers/w1/slaves/w1_ds2760.c | 48 +- drivers/w1/slaves/w1_ds2780.c | 48 +- drivers/w1/slaves/w1_smem.c | 4 +- drivers/w1/slaves/w1_therm.c | 13 +- drivers/w1/w1.c | 6 +- drivers/w1/w1.h | 2 +- drivers/w1/w1_family.c | 3 +- drivers/w1/w1_family.h | 5 +- drivers/w1/w1_int.c | 5 +- drivers/w1/w1_int.h | 2 +- drivers/w1/w1_io.c | 7 +- drivers/w1/w1_log.h | 2 +- drivers/w1/w1_netlink.c | 27 +- drivers/w1/w1_netlink.h | 2 +- 2180 files changed, 94743 insertions(+), 76570 deletions(-) delete mode 100644 drivers/media/common/tuners/tda18212_priv.h delete mode 100644 drivers/pci/dmar.c delete mode 100644 drivers/pci/intel-iommu.c delete mode 100644 drivers/pci/intr_remapping.c delete mode 100644 drivers/pci/intr_remapping.h delete mode 100644 drivers/pci/iova.c delete mode 100644 drivers/staging/ft1000/ft1000-pcmcia/ft1000.conf delete mode 100644 drivers/staging/ft1000/ft1000-pcmcia/ft1000_dev.h create mode 100644 drivers/video/logo/.gitignore 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 #include #include +#include #include #include @@ -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 #include #include +#include #include #include #include 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 #include #include +#include #include #include #include @@ -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 #include #include +#include #include #include @@ -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 #include +#include #include #include #include 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 #include #include +#include +#include #include #include @@ -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 #include +#include #include #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 #include #include +#include #include #include #include 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 #include #include #include 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 #include #include 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 +#include #include #include @@ -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 #include #include +#include #include #include @@ -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 #include +#include #include #include 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 #include #include +#include #include #include #include @@ -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(¤t->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(¤t->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 #include 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 #include +#include #include +#include #include #include @@ -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 #include #include +#include #include #include #include @@ -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 -#include +#include #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 + #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 #include #include +#include #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 #include -#include +#include #include #include #include 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 #include #include +#include #include #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 #include #include +#include #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 #include #include +#include #include #include #include #include #include +#include #include #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(¤t->cpus_allowed) && - !cpumask_full(¤t->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, ¤t->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 #include +#include #include +#include #include #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 +#include #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 +#include #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(¤t->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(¤t->mm->mmap_sem); ret = ipath_user_sdma_queue_pkts(dd, pq, &list, iov, dim, mxp); - up_write(¤t->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 #include #include +#include #include #include 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 #include +#include #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 +#include #include #include 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 #include #include +#include #include #include #include @@ -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 #include +#include #include +#include #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(¶m, 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, ¶m, port, &status); + err = mthca_INIT_IB(dev, ¶m, 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 +#include #include #include #include @@ -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 #include #include +#include #include #include 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 #include #include +#include #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 #include #include +#include #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 #include #include +#include #include #include @@ -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 #include #include +#include #include #include @@ -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 #include #include +#include #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 + #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 #include #include +#include #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 #include +#include #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 #include +#include #include #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 #include +#include #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 #include #include +#include #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(¤t->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(¤t->mm->mmap_sem); ret = qib_user_sdma_queue_pkts(dd, pq, &list, iov, dim, mxp); - up_write(¤t->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 #include #include +#include #include #include #include +#include +#include #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 #include -#include +#include #include #include 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 #include #include +#include #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 +#include #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 +#include #include #include @@ -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 #include +#include #include #include #include @@ -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 #include #include +#include #include @@ -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 #include +#include #include #include #include @@ -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 #include -#include +#include #include #include @@ -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 +#include #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 +#include #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 #include #include +#include #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 +#include #include #include #include @@ -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 "); +MODULE_AUTHOR("Hans-Christian Egtvedt "); 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 #include +#include #include #include #include @@ -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 */ 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 #include #include @@ -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 #include -#include #include #include #include @@ -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 -#include #include #include #include @@ -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 #include #include +#include #include #include 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 "); +MODULE_AUTHOR("Hans-Christian Egtvedt "); 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 #include #include #include @@ -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 #include #include +#include MODULE_AUTHOR("Vojtech Pavlik "); 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 #include #include - +#include #include #include 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 * Copyright (c) 2001 Frederic Lepied * Copyright (c) 2004 Panagiotis Issaris - * Copyright (c) 2002-2009 Ping Cheng + * Copyright (c) 2002-2011 Ping Cheng * * 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 " #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 +#include /* 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 #include #include +#include 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 #include +#include /* 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 #include #include +#include /* 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 #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 #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 #include #include -#include +#include #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 +#include #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 #include +#include /*** 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 #include #include #include 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 #include #include #include 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 #include #include #include 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 #include #include #include 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 #include #include #include 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 #include #include +#include #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 #include #include #include 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 #include #include #include 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 #include #include #include 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 #include #include +#include #include #include #include @@ -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 #include +#include #include #include #include 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 +#include 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 #include #include +#include #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 #include #include +#include #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 #include #include +#include #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 #include +#include #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 _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 #include #include +#include #include #include #include @@ -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 #include @@ -11,6 +13,7 @@ #include #include #include +#include #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 #include #include -#include #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 +#include 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 +#include /****************************************************************************/ /* 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 +#include #include 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 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 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 #include +#include 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 = ®, .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 - * - * 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 +#include #include #include @@ -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 #include #include 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 #include #include +#include #include #include #include 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 "); 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 #include +#include #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 #include #include -#include #include #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 #include #include +#include #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 #include #include @@ -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 #include #include +#include #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 #include +#include #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 #include #include +#include #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 #include #include +#include #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 #include +#include #include #include 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 #include #include +#include #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 #include #include +#include #include #include #include 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 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 . #ifndef __SMS_CORE_API_H__ #define __SMS_CORE_API_H__ -#include #include #include #include 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 #include #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 #include #include +#include #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 . #include #include #include +#include #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 #include #include @@ -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 #include +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 #include #include -#include #include #include #include -#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 + #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 "); 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 #include #include -#include #include #include #include @@ -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 #include #include @@ -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 #include #include @@ -57,6 +59,7 @@ #include +#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 #include #include @@ -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 #include #include @@ -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(" addr << 1, msg->buf[0]); - if (!(xmit & BT878_I2C_NOSTOP)) - printk(" >\n"); + pr_cont(" 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(" 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(" 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 #include #include @@ -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 #include #include @@ -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 #include #include @@ -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 -#define BTTV_VERSION_CODE KERNEL_VERSION(0,9,18) - #include #include #include @@ -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 #include #include #include @@ -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 #include #include +#include #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 ****************************************************************************/ -#include - +#define CPIA_VERSION "3.0.1" #include #include @@ -80,6 +79,7 @@ MODULE_AUTHOR("Steve Miller (STMicroelectronics) "); 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 #include #include #include @@ -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 #include #include -#include #include #include #include @@ -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 " #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 #include #include #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 #include #include +#include -#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 "); 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, ¶ms); 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, ¶ms); v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, ¶ms); } + 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 + MODULE_DESCRIPTION("v4l2 driver module for cx23885 based TV cards"); MODULE_AUTHOR("Steven Toth "); 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 #include -#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 #include +#include #include #include @@ -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 "); 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 , Gerd Knorr [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 "); MODULE_AUTHOR("Gerd Knorr [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 "); MODULE_AUTHOR("Chris Pascoe "); MODULE_AUTHOR("Gerd Knorr [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 [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 #include -#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 #include #include +#include #include #include 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 #include #include +#include #include #include 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 #include #include -#include #include #include #include @@ -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 -#include #include #include #include @@ -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 #include #include -#include #include #include @@ -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 -#include #include #include #include @@ -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 * - * Copyright (C) 2007 Mauro Carvalho Chehab + * Copyright (C) 2007-2011 Mauro Carvalho Chehab * - 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 #include #include +#include #include #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 "); -MODULE_AUTHOR("Mauro Carvalho Chehab "); +MODULE_AUTHOR("Mauro Carvalho Chehab "); 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<= 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<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<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<= EM28XX_MAXBOARDS) { - printk(DRIVER_NAME ": Supports only %i em28xx boards.\n", - EM28XX_MAXBOARDS); - em28xx_devused &= ~(1<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<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<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 + (c) 2008-2011 Mauro Carvalho Chehab (c) 2008 Devin Heitmueller - 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 "); @@ -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 #include #include -#include #include #include #include @@ -50,7 +49,8 @@ "Sascha Sommer " #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 #include #include #include @@ -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 #include #include #include @@ -48,8 +51,7 @@ #define ET61X251_MODULE_AUTHOR "(C) 2006-2007 Luca Risolia" #define ET61X251_AUTHOR_EMAIL "" #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 @@ -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 . */ + +#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 #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 -#include #include #include #include @@ -54,8 +55,7 @@ MODULE_AUTHOR("Jean-François Moine "); 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 @@ -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 "); 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 @@ -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 #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, ®); 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 @@ -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 * Copyright (C) 2008 Jim Paris * @@ -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 "); 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 @@ -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 @@ -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 @@ -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 #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 + * Copyright (C) 2009-2011 Jean-François Moine * 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 @@ -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 @@ -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 @@ -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 @@ -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 #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 @@ -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 @@ -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 @@ -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 #include #include -#include +#include #include #include #include @@ -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 #include +#include #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 #include #include -#include #include #include @@ -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 #include -#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 #include #include #include 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 @@ -19,24 +19,12 @@ #include #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 #include #include -#include #include #include #include -#include #include #include #include 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 @@ -14,186 +14,285 @@ */ #include +#include #include #include #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, ®); + 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 @@ -18,11 +18,10 @@ #include #include #include -#include #include #include #include -#include +#include #include #include #include @@ -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,1167 +69,371 @@ 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, -}; - -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, +#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 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) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct device *cdev = &client->dev; - struct i2c_msg msg[1]; - u8 wbuf[I2C_MAX + 4]; - u32 *buf = (u32 *)&wbuf[4]; + u32 val_32; 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 (I2C_SIZE(reg) != 1) { + v4l2_err(sd, "Wrong data size\n"); return -EINVAL; } - msg->addr = client->addr; - msg->flags = 0; - msg->len = size + 4; - msg->buf = wbuf; - wbuf[0] = size + 4; - wbuf[1] = M5MOLS_BYTE_WRITE; - wbuf[2] = category; - wbuf[3] = cmd; - - *buf = m5mols_swap_byte((u8 *)&val, size); - - 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); + ret = m5mols_read(sd, I2C_SIZE(reg), reg, &val_32); + if (ret) return ret; - } - - usleep_range(15000, 20000); /* must be for stabilization */ - return 0; + *val = (u8)val_32; + return ret; } -int m5mols_check_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u32 value) +int m5mols_read_u16(struct v4l2_subdev *sd, u32 reg, u16 *val) { - u32 busy, i; + u32 val_32; int ret; - for (i = 0; i < M5MOLS_I2C_CHECK_RETRY; i++) { - ret = m5mols_read_reg(sd, I2C_8BIT, category, cmd, &busy); - if (ret < 0) - return ret; - - if (busy == value) /* bingo */ - return 0; - - /* must be for stabilization */ - usleep_range(10000, 10000); - } - return -EBUSY; -} - -/* - * m5mols_set_mode - change and set mode of M5MOLS. - * - * This driver supports now only 3 modes(System, Monitor, Parameter). - */ -int m5mols_set_mode(struct v4l2_subdev *sd, enum m5mols_mode 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_mode[] = { - "System initialization", - "Parameter setting", - "Monitor setting", - "Capture setting", - "Unknown", - }; - int ret = 0; - - if (mode < MODE_SYSINIT || mode > MODE_UNKNOWN) + if (I2C_SIZE(reg) != 2) { + v4l2_err(sd, "Wrong data size\n"); 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]); - - return ret; -} - -/* - * m5mols_get_status - get status of M5MOLS. - */ -enum m5mols_status m5mols_get_status(struct v4l2_subdev *sd) -{ - 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; - ret = i2c_r8_system(sd, CAT0_STATUS, ®); + ret = m5mols_read(sd, I2C_SIZE(reg), reg, &val_32); 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]); - + *val = (u16)val_32; return ret; } -/* - * get_version - get M5MOLS sensor versions. - */ -static int get_version(struct v4l2_subdev *sd) +int m5mols_read_u32(struct v4l2_subdev *sd, u32 reg, u32 *val) { - 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; + if (I2C_SIZE(reg) != 4) { + v4l2_err(sd, "Wrong data size\n"); + return -EINVAL; } - info->ver = value.ver; - - 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); - - 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); - - 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); + return m5mols_read(sd, I2C_SIZE(reg), reg, val); } -/* - * 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. +/** + * m5mols_write - I2C command write function + * @reg: combination of size, category and command for the I2C packet + * @val: value to write */ -static int get_res_preset(struct v4l2_subdev *sd, u16 width, u16 height, - enum m5mols_res_type type) +int m5mols_write(struct v4l2_subdev *sd, u32 reg, u32 val) { - struct m5mols_info *info = to_m5mols(sd); - int i; + struct i2c_client *client = v4l2_get_subdevdata(sd); + 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; - 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)) - break; - } + if (!client->adapter) + return -ENODEV; - if (i >= ARRAY_SIZE(m5mols_resolutions)) { - v4l2msg("no matching resolution\n"); + if (size != 1 && size != 2 && size != 4) { + v4l2_err(sd, "Wrong data size\n"); return -EINVAL; } - return m5mols_resolutions[i].value; -} + msg->addr = client->addr; + msg->flags = 0; + msg->len = (u16)size + 4; + msg->buf = wbuf; + wbuf[0] = size + 4; + wbuf[1] = M5MOLS_BYTE_WRITE; + wbuf[2] = category; + wbuf[3] = cmd; -/* - * get_fps - calc & check FPS from v4l2_captureparm, if FPS is adequate, set. - * - * 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. - */ -static int get_fps(struct v4l2_subdev *sd, - struct v4l2_captureparm *parm) -{ - int numerator = parm->timeperframe.numerator; - int denominator = parm->timeperframe.denominator; + *buf = m5mols_swap_byte((u8 *)&val, size); - /* The denominator should be +, except 0. The numerator shoud be +. */ - if (numerator < 0 || denominator <= 0) - return -EINVAL; + usleep_range(200, 200); - /* The numerator is 0, return auto fps. */ - if (numerator == 0) { - parm->timeperframe.denominator = M5MOLS_FPS_AUTO; - return 0; + ret = i2c_transfer(client->adapter, msg, 1); + if (ret < 0) { + v4l2_err(sd, "write failed: size:%d cat:%02x cmd:%02x. %d\n", + size, category, cmd, ret); + return ret; } - /* calc FPS(not time per frame) per 1 numerator */ - denominator = denominator / numerator; - - if (denominator < M5MOLS_FPS_AUTO || denominator > M5MOLS_FPS_MAX) - return -EINVAL; - - if (!m5mols_reg_fps[denominator]) - return -EINVAL; - - 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; -} - -/* - * to_res_type - return resolution type of M5MOLS according to pixelcode. - */ -static enum m5mols_res_type to_res_type(struct v4l2_subdev *sd, - enum v4l2_mbus_pixelcode code) -{ - int i = ARRAY_SIZE(m5mols_formats); - - while (i--) - if (code == m5mols_formats[i].code) - break; - if (i < 0) - return M5MOLS_RES_MAX; - - if (code == m5mols_formats[M5MOLS_RES_MON].code) - return M5MOLS_RES_MON; - else - return M5MOLS_RES_CAPTURE; -} - -static int m5mols_g_mbus_fmt(struct v4l2_subdev *sd, - struct v4l2_mbus_framefmt *ffmt) -{ - struct m5mols_info *info = to_m5mols(sd); - enum m5mols_res_type res_type; - - res_type = to_res_type(sd, ffmt->code); - if (res_type == M5MOLS_RES_MAX) - return -EINVAL; - - *ffmt = info->fmt[res_type]; - info->code = ffmt->code; - return 0; } -static int m5mols_into_monitor(struct v4l2_subdev *sd, int res_size) +int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u8 mask) { + u8 busy; + int i; 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); - - return ret; + for (i = 0; i < M5MOLS_I2C_CHECK_RETRY; i++) { + ret = m5mols_read_u8(sd, I2C_REG(category, cmd, 1), &busy); + if (ret < 0) + return ret; + if ((busy & mask) == mask) + return 0; + } + return -EBUSY; } -static int m5mols_into_capture(struct v4l2_subdev *sd, int res_size) +/** + * m5mols_enable_interrupt - Clear interrupt pending bits and unmask interrupts + * + * Before writing desired interrupt value the INT_FACTOR register should + * be read to clear pending interrupts. + */ +int m5mols_enable_interrupt(struct v4l2_subdev *sd, u8 reg) { 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, ®); - 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)); + u8 mask = is_available_af(info) ? REG_INT_AF : 0; + u8 dummy; + int ret; - /* disable all interrupt & clear interrupt */ - ret = i2c_w8_system(sd, CAT0_INT_ENABLE, 0x0); + ret = m5mols_read_u8(sd, SYSTEM_INT_FACTOR, &dummy); if (!ret) - ret = i2c_r8_system(sd, CAT0_INT_FACTOR, ®); - if (ret) - return -EPERM; - - /* If all timeout exhausted, return error. */ - if (!timeout) - return -ETIMEDOUT; - - ret = i2c_r32_capt_ctrl(sd, CATC_CAP_IMAGE_SIZE, &temp); - info->captured = false; - return ret; -} - -static int m5mols_s_mbus_fmt(struct v4l2_subdev *sd, - struct v4l2_mbus_framefmt *ffmt) -{ - 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); - - info->fmt[res_type] = default_fmt[res_type]; - info->fmt[res_type].width = ffmt->width; - info->fmt[res_type].height = ffmt->height; - - *ffmt = info->fmt[res_type]; - info->code = ffmt->code; - + ret = m5mols_write(sd, SYSTEM_INT_ENABLE, reg & ~mask); 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; - - *code = m5mols_formats[index].code; - - return 0; -} - -static int m5mols_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) +/** + * 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. + */ +static int m5mols_reg_mode(struct v4l2_subdev *sd, u8 mode) { - 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) - return -EINVAL; + int ret = m5mols_write(sd, SYSTEM_SYSMODE, mode); - cp->capability = V4L2_CAP_TIMEPERFRAME; - cp->timeperframe = info->tpf; - - return 0; + return ret ? ret : m5mols_busy(sd, CAT_SYSTEM, CAT0_SYSMODE, mode); } -static int m5mols_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) +/** + * 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. + */ +int m5mols_mode(struct m5mols_info *info, u8 mode) { - struct m5mols_info *info = to_m5mols(sd); - struct v4l2_captureparm *cp = &parms->parm.capture; + struct v4l2_subdev *sd = &info->sd; int ret = -EINVAL; + u8 reg; - if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && - parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) - return -EINVAL; - - 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; - } - - v4l2msg("denominator: %d / numerator: %d.\n", - cp->timeperframe.denominator, cp->timeperframe.numerator); - - return ret; -} - -static int m5mols_get_info_capture(struct v4l2_subdev *sd) -{ - 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) + if (mode < REG_PARAMETER || mode > REG_CAPTURE) return 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); - if (!ret) - ret = i2c_r16_exif(sd, CAT7_INFO_SDR, (u32 *)&exif->sdr); - if (!ret) - ret = i2c_r16_exif(sd, CAT7_INFO_QVAL, (u32 *)&exif->qval); - if (ret) + ret = m5mols_read_u8(sd, SYSTEM_SYSMODE, ®); + if ((!ret && reg == mode) || ret) return ret; - if (!ret) - ret = i2c_r32_capt_ctrl(sd, CATC_CAP_IMAGE_SIZE, - &info->cap.main); - 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); - - return ret; -} - -/* TODO: not verified. */ -static int m5mols_start_capture(struct v4l2_subdev *sd) -{ - 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, ®); - 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); - - 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); + switch (reg) { + case REG_PARAMETER: + ret = m5mols_reg_mode(sd, REG_MONITOR); + if (!ret && mode == REG_MONITOR) + break; if (!ret) - ret = i2c_r8_system(sd, CAT0_INT_FACTOR, ®); - if (ret) - return -EPERM; - - /* If all timeout exhausted, return error. */ - if (!timeout) - return -ETIMEDOUT; - - info->captured = false; - - ret = 0; - } - - /* 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); + ret = m5mols_reg_mode(sd, REG_CAPTURE); + break; - 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); + case REG_MONITOR: + if (mode == REG_PARAMETER) { + ret = m5mols_reg_mode(sd, REG_PARAMETER); + break; } - return -EINVAL; - } else { - if (is_streaming(sd)) - return m5mols_set_mode(sd, MODE_PARMSET); - return -EINVAL; - } -} - -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, -}; - -static int m5mols_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct v4l2_subdev *sd = to_sd(ctrl); - int ret; - - ret = m5mols_set_mode_backup(sd, MODE_PARMSET); - 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_reg_mode(sd, REG_CAPTURE); + break; - switch (ctrl->id) { - case V4L2_CID_CAM_JPEG_ENCODEDSIZE: - ctrl->cur.val = info->cap.total; + 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; + default: - ret = -EINVAL; - break; + v4l2_warn(sd, "Wrong mode: %d\n", mode); } - return ret; -} - -static const struct v4l2_ctrl_ops m5mols_ctrl_ops = { - .s_ctrl = m5mols_s_ctrl, - .g_volatile_ctrl = m5mols_g_volatile_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); - int ret; - - if (enable) { - if (is_powerup(sd)) - return 0; - - /* power-on additional power */ - if (info->set_power) { - ret = info->set_power(&c->dev, 1); - if (ret) - return ret; - } - - ret = regulator_bulk_enable(ARRAY_SIZE(supplies), supplies); - if (ret) - return ret; - - gpio_set_value(info->pdata->gpio_rst, info->pdata->enable_rst); - 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; - - /* power-off additional power */ - if (info->set_power) { - ret = info->set_power(&c->dev, 0); - if (ret) - return ret; - } - - info->power = false; - - gpio_set_value(info->pdata->gpio_rst, !info->pdata->enable_rst); - usleep_range(1000, 1000); - } + if (!ret) + info->mode = mode; return ret; } -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, ®); - 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, ®); - 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; - } - } - } -} - -static irqreturn_t m5mols_irq_handler(int irq, void *data) -{ - 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; -} - -/* - * m5mols_sensor_armboot - booting M5MOLS internal ARM core-controller. +/** + * m5mols_get_version - retrieve full revisions information of M-5MOLS * - * 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. + * The version information includes revisions of hardware and firmware, + * AutoFocus alghorithm version and the version string. */ -static int m5mols_sensor_armboot(struct v4l2_subdev *sd) +static int m5mols_get_version(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); - if (ret < 0) - return ret; - - msleep(500); - dev_dbg(&client->dev, "Success ARM Booting\n"); - - /* after ARM booting, the M5MOLS state changed Parameter mode. */ - info->mode = MODE_PARMSET; - - ret = i2c_r8_system(sd, CAT0_INT_FACTOR, ®); /* clear intterupt */ - if (!ret) - ret = i2c_w8_system(sd, CAT0_INT_ENABLE, 0x0); /* all disable */ - if (!ret) - ret = get_version(sd); - if (!ret) - ret = i2c_w8_param(sd, CAT1_DATA_INTERFACE, m5mols_mipi_value); - - m5mols_show_version(sd); - - 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; + struct m5mols_version *ver = &info->ver; + u8 *str = ver->str; + int i; int ret; - /* check minimum & maximum of M5MOLS controls */ - ret = i2c_r16_ae(sd, CAT3_MAX_GAIN_MON, (u32 *)&max_ex_mon); - 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); - info->autowb = v4l2_ctrl_new_std(&info->handle, - &m5mols_ctrl_ops, V4L2_CID_AUTO_WHITE_BALANCE, - 0, 1, 1, 1); - info->saturation = v4l2_ctrl_new_std(&info->handle, - &m5mols_ctrl_ops, V4L2_CID_SATURATION, - 0, 6, 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); - - sd->ctrl_handler = &info->handle; - - if (info->handle.error) { - dev_err(&client->dev, "Failed to init 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. - */ -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); + ret = m5mols_read_u8(sd, SYSTEM_VER_CUSTOMER, &ver->customer); if (!ret) - ret = i2c_w8_param(sd, CAT1_MONITOR_FPS, - m5mols_reg_fps[default_fps.denominator]); + ret = m5mols_read_u8(sd, SYSTEM_VER_PROJECT, &ver->project); if (!ret) - ret = m5mols_init_controls(info); + ret = m5mols_read_u16(sd, SYSTEM_VER_FIRMWARE, &ver->fw); if (!ret) - ret = m5mols_set_ae_lock(info, false); + ret = m5mols_read_u16(sd, SYSTEM_VER_HARDWARE, &ver->hw); 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); - int 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; - if (on) { - ret = m5mols_sensor_power(info, true); - if (!ret) - ret = m5mols_sensor_armboot(sd); - if (!ret) - ret = m5mols_setup_default(sd); - } else { - ret = m5mols_sensor_power(info, false); + for (i = 0; i < VERSION_STRING_SIZE; i++) { + ret = m5mols_read_u8(sd, SYSTEM_VER_STRING, &str[i]); + if (ret) + return ret; } - return ret; -} + 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); -static int m5mols_log_status(struct v4l2_subdev *sd) -{ - struct m5mols_info *info = to_m5mols(sd); + 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); - v4l2_ctrl_handler_log_status(&info->handle, sd->name); + if (!is_available_af(info)) + v4l2_info(sd, "No support Auto Focus on this firmware\n"); - return 0; + return ret; } -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 @@ -1271,7 +443,7 @@ 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) + if (code == m5mols_default_ffmt[type].code) return type; } while (type++ != SIZE_DEFAULT_FFMT); @@ -1292,10 +464,10 @@ static int __find_resolution(struct v4l2_subdev *sd, enum m5mols_restype *type, u32 *resolution) { - const struct m5mols_resolution *fsize = &m5mols_resolutions[0]; + 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_resolutions); + int i = ARRAY_SIZE(m5mols_reg_res); unsigned int min_err = ~0; while (i--) { @@ -1314,7 +486,7 @@ static int __find_resolution(struct v4l2_subdev *sd, if (match) { mf->width = match->width; mf->height = match->height; - *resolution = match->value; + *resolution = match->reg; *type = stype; return 0; } @@ -1330,7 +502,7 @@ static struct v4l2_mbus_framefmt *__find_format(struct m5mols_info *info, if (which == V4L2_SUBDEV_FORMAT_TRY) return fh ? v4l2_subdev_get_try_format(fh, 0) : NULL; - return &info->fmt[type]; + return &info->ffmt[type]; } static int m5mols_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, @@ -1339,9 +511,6 @@ static int m5mols_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, 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; @@ -1360,9 +529,6 @@ static int m5mols_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, u32 resolution = 0; int ret; - if (fmt->pad != 0) - return -EINVAL; - ret = __find_resolution(sd, format, &type, &resolution); if (ret < 0) return ret; @@ -1371,13 +537,14 @@ static int m5mols_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, if (!sfmt) return 0; - sfmt = &default_fmt[type]; - sfmt->width = format->width; - sfmt->height = format->height; + + format->code = m5mols_default_ffmt[type].code; + format->colorspace = V4L2_COLORSPACE_JPEG; + format->field = V4L2_FIELD_NONE; if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) { + *sfmt = *format; info->resolution = resolution; - info->code = format->code; info->res_type = type; } @@ -1391,7 +558,7 @@ static int m5mols_enum_mbus_code(struct v4l2_subdev *sd, if (!code || code->index >= SIZE_DEFAULT_FFMT) return -EINVAL; - code->code = default_fmt[code->index].code; + code->code = m5mols_default_ffmt[code->index].code; return 0; } @@ -1402,183 +569,453 @@ static struct v4l2_subdev_pad_ops m5mols_pad_ops = { .set_fmt = m5mols_set_fmt, }; -static const struct v4l2_subdev_ops m5mols_ops = { - .core = &m5mols_core_ops, - .pad = &m5mols_pad_ops, - .video = &m5mols_video_ops, +/** + * 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) +{ + int ret = -EINVAL; + + if (!is_ctrl_synced(info)) { + ret = m5mols_do_scenemode(info, REG_SCENE_NORMAL); + if (ret) + return ret; + + v4l2_ctrl_handler_setup(&info->handle); + info->ctrl_sync = true; + } + + return ret; +} + +/** + * 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 v4l2_subdev *sd = &info->sd; + int ret; + + ret = m5mols_mode(info, REG_PARAMETER); + if (!ret) + ret = m5mols_write(sd, PARM_MON_SIZE, info->resolution); + if (!ret) + ret = m5mols_write(sd, PARM_MON_FPS, REG_FPS_30); + if (!ret) + ret = m5mols_mode(info, REG_MONITOR); + if (!ret) + ret = m5mols_sync_controls(info); + + return ret; +} + +static int m5mols_s_stream(struct v4l2_subdev *sd, int enable) +{ + struct m5mols_info *info = to_m5mols(sd); + u32 code = info->ffmt[info->res_type].code; + + if (enable) { + int ret = -EINVAL; + + if (is_code(code, M5MOLS_RESTYPE_MONITOR)) + ret = m5mols_start_monitor(info); + if (is_code(code, M5MOLS_RESTYPE_CAPTURE)) + ret = m5mols_start_capture(info); + + return ret; + } + + return m5mols_mode(info, REG_PARAMETER); +} + +static const struct v4l2_subdev_video_ops m5mols_video_ops = { + .s_stream = m5mols_s_stream, }; -static int m5mols_link_setup(struct media_entity *entity, - const struct media_pad *local, - const struct media_pad *remote, u32 flags) +static int m5mols_s_ctrl(struct v4l2_ctrl *ctrl) { - printk("%s\n", __func__); - return 0; + struct v4l2_subdev *sd = to_sd(ctrl); + struct m5mols_info *info = to_m5mols(sd); + int ret; + + info->mode_save = info->mode; + + ret = m5mols_mode(info, REG_PARAMETER); + if (!ret) + ret = m5mols_set_ctrl(ctrl); + if (!ret) + ret = m5mols_mode(info, info->mode_save); + + return ret; } -static const struct media_entity_operations m5mols_media_ops = { - .link_setup = m5mols_link_setup, + +static const struct v4l2_ctrl_ops m5mols_ctrl_ops = { + .s_ctrl = m5mols_s_ctrl, }; -static int m5mols_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +static int m5mols_sensor_power(struct m5mols_info *info, bool enable) { - struct v4l2_subdev_format format; + struct v4l2_subdev *sd = &info->sd; + struct i2c_client *client = v4l2_get_subdevdata(sd); + const struct m5mols_platform_data *pdata = info->pdata; + 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 (enable) { + if (is_powered(info)) + return 0; - m5mols_set_fmt(sd, fh, &format); + if (info->set_power) { + ret = info->set_power(&client->dev, 1); + if (ret) + return ret; + } - return 0; + ret = regulator_bulk_enable(ARRAY_SIZE(supplies), supplies); + if (ret) { + info->set_power(&client->dev, 0); + return ret; + } + + gpio_set_value(pdata->gpio_reset, !pdata->reset_polarity); + usleep_range(1000, 1000); + info->power = true; + + return ret; + } + + if (!is_powered(info)) + return 0; + + ret = regulator_bulk_disable(ARRAY_SIZE(supplies), supplies); + if (ret) + return ret; + + if (info->set_power) + info->set_power(&client->dev, 0); + + gpio_set_value(pdata->gpio_reset, pdata->reset_polarity); + usleep_range(1000, 1000); + info->power = false; + + return ret; } -static int m5mols_subdev_close(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh) +/* m5mols_update_fw - optional firmware update routine */ +int __attribute__ ((weak)) m5mols_update_fw(struct v4l2_subdev *sd, + int (*set_power)(struct m5mols_info *, bool)) { - v4l2_dbg(1, m5mols_debug, sd, "%s", __func__); return 0; } -static int m5mols_subdev_registered(struct v4l2_subdev *sd) +/** + * m5mols_sensor_armboot - Booting M-5MOLS internal ARM core. + * + * 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) +{ + int ret; + + ret = m5mols_write(sd, FLASH_CAM_START, REG_START_ARM_BOOT); + if (ret < 0) + return ret; + + msleep(520); + + ret = m5mols_get_version(sd); + if (!ret) + ret = m5mols_update_fw(sd, m5mols_sensor_power); + if (ret) + return ret; + + 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; +} + +static int m5mols_init_controls(struct m5mols_info *info) { - v4l2_dbg(1, m5mols_debug, sd, "%s", __func__); + struct v4l2_subdev *sd = &info->sd; + u16 max_exposure; + u16 step_zoom; + int ret; + + /* 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; + + 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, 0); + info->saturation = v4l2_ctrl_new_std(&info->handle, + &m5mols_ctrl_ops, V4L2_CID_SATURATION, + 1, 5, 1, 3); + info->zoom = v4l2_ctrl_new_std(&info->handle, + &m5mols_ctrl_ops, V4L2_CID_ZOOM_ABSOLUTE, + 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) { + 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); + return 0; } -static void m5mols_subdev_unregistered(struct v4l2_subdev *sd) +/** + * 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_s_power(struct v4l2_subdev *sd, int on) +{ + struct m5mols_info *info = to_m5mols(sd); + int ret; + + if (on) { + ret = m5mols_sensor_power(info, true); + if (!ret) + ret = m5mols_sensor_armboot(sd); + if (!ret) + 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; +} + +static int m5mols_log_status(struct v4l2_subdev *sd) { - v4l2_dbg(1, m5mols_debug, sd, "%s", __func__); + struct m5mols_info *info = to_m5mols(sd); + + v4l2_ctrl_handler_log_status(&info->handle, sd->name); + + return 0; } -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 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, +}; + +static const struct v4l2_subdev_ops m5mols_ops = { + .core = &m5mols_core_ops, + .pad = &m5mols_pad_ops, + .video = &m5mols_video_ops, }; -static int m5mols_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static void m5mols_irq_work(struct work_struct *work) +{ + struct m5mols_info *info = + container_of(work, struct m5mols_info, work_irq); + struct v4l2_subdev *sd = &info->sd; + u8 reg; + int ret; + + if (!is_powered(info) || + m5mols_read_u8(sd, SYSTEM_INT_FACTOR, &info->interrupt)) + return; + + switch (info->interrupt & REG_INT_MASK) { + case REG_INT_AF: + if (!is_available_af(info)) + break; + ret = m5mols_read_u8(sd, AF_STATUS, ®); + 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); + + v4l2_dbg(2, m5mols_debug, sd, "CAPTURE\n"); + break; + default: + v4l2_dbg(2, m5mols_debug, sd, "Undefined: %02x\n", reg); + break; + }; +} + +static irqreturn_t m5mols_irq_handler(int irq, void *data) +{ + struct v4l2_subdev *sd = data; + struct m5mols_info *info = to_m5mols(sd); + + schedule_work(&info->work_irq); + + return IRQ_HANDLED; +} + +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; - 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; - } - } + info->pdata = pdata; + info->set_power = pdata->set_power; - 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 "); MODULE_AUTHOR("Dongsoo Kim "); -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 @@ -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 #include #include -#include #include #include +#include #include #include @@ -45,18 +45,17 @@ #include #include -#include #include #include